blob: 5f29fe401efbcc8c46e96d0c9174f78dd1dc3075 [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,
philipel8aadd502017-02-23 02:56:13 -0800216 const PacedPacketInfo& pacing_info) override {
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100217 RTC_DCHECK(pacer_thread_.CalledOnValidThread());
218 rtc::CritScope lock(&crit_);
219 if (feedback_observer_)
philipel8aadd502017-02-23 02:56:13 -0800220 feedback_observer_->AddPacket(sequence_number, length, pacing_info);
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100221 }
philipel8aadd502017-02-23 02:56:13 -0800222
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100223 void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override {
224 RTC_DCHECK(network_thread_.CalledOnValidThread());
225 rtc::CritScope lock(&crit_);
michaelt9960bb12016-10-18 09:40:34 -0700226 if (feedback_observer_)
227 feedback_observer_->OnTransportFeedback(feedback);
Stefan Holmer60e43462016-09-07 09:58:20 +0200228 }
229 std::vector<PacketInfo> GetTransportFeedbackVector() const override {
230 RTC_NOTREACHED();
231 return std::vector<PacketInfo>();
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100232 }
233
234 private:
235 rtc::CriticalSection crit_;
236 rtc::ThreadChecker thread_checker_;
237 rtc::ThreadChecker pacer_thread_;
238 rtc::ThreadChecker network_thread_;
239 TransportFeedbackObserver* feedback_observer_ GUARDED_BY(&crit_);
240};
241
242class TransportSequenceNumberProxy : public TransportSequenceNumberAllocator {
243 public:
244 TransportSequenceNumberProxy() : seq_num_allocator_(nullptr) {
245 pacer_thread_.DetachFromThread();
246 }
247
248 void SetSequenceNumberAllocator(
249 TransportSequenceNumberAllocator* seq_num_allocator) {
250 RTC_DCHECK(thread_checker_.CalledOnValidThread());
251 rtc::CritScope lock(&crit_);
252 seq_num_allocator_ = seq_num_allocator;
253 }
254
255 // Implements TransportSequenceNumberAllocator.
256 uint16_t AllocateSequenceNumber() override {
257 RTC_DCHECK(pacer_thread_.CalledOnValidThread());
258 rtc::CritScope lock(&crit_);
259 if (!seq_num_allocator_)
260 return 0;
261 return seq_num_allocator_->AllocateSequenceNumber();
262 }
263
264 private:
265 rtc::CriticalSection crit_;
266 rtc::ThreadChecker thread_checker_;
267 rtc::ThreadChecker pacer_thread_;
268 TransportSequenceNumberAllocator* seq_num_allocator_ GUARDED_BY(&crit_);
269};
270
271class RtpPacketSenderProxy : public RtpPacketSender {
272 public:
kwiberg55b97fe2016-01-28 05:22:45 -0800273 RtpPacketSenderProxy() : rtp_packet_sender_(nullptr) {}
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100274
275 void SetPacketSender(RtpPacketSender* rtp_packet_sender) {
276 RTC_DCHECK(thread_checker_.CalledOnValidThread());
277 rtc::CritScope lock(&crit_);
278 rtp_packet_sender_ = rtp_packet_sender;
279 }
280
281 // Implements RtpPacketSender.
282 void InsertPacket(Priority priority,
283 uint32_t ssrc,
284 uint16_t sequence_number,
285 int64_t capture_time_ms,
286 size_t bytes,
287 bool retransmission) override {
288 rtc::CritScope lock(&crit_);
289 if (rtp_packet_sender_) {
290 rtp_packet_sender_->InsertPacket(priority, ssrc, sequence_number,
291 capture_time_ms, bytes, retransmission);
292 }
293 }
294
295 private:
296 rtc::ThreadChecker thread_checker_;
297 rtc::CriticalSection crit_;
298 RtpPacketSender* rtp_packet_sender_ GUARDED_BY(&crit_);
299};
300
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000301class VoERtcpObserver : public RtcpBandwidthObserver {
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000302 public:
stefan7de8d642017-02-07 07:14:08 -0800303 explicit VoERtcpObserver(Channel* owner)
304 : owner_(owner), bandwidth_observer_(nullptr) {}
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000305 virtual ~VoERtcpObserver() {}
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000306
stefan7de8d642017-02-07 07:14:08 -0800307 void SetBandwidthObserver(RtcpBandwidthObserver* bandwidth_observer) {
308 rtc::CritScope lock(&crit_);
309 bandwidth_observer_ = bandwidth_observer;
310 }
311
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000312 void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
stefan7de8d642017-02-07 07:14:08 -0800313 rtc::CritScope lock(&crit_);
314 if (bandwidth_observer_) {
315 bandwidth_observer_->OnReceivedEstimatedBitrate(bitrate);
316 }
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000317 }
318
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000319 void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
320 int64_t rtt,
321 int64_t now_ms) override {
stefan7de8d642017-02-07 07:14:08 -0800322 {
323 rtc::CritScope lock(&crit_);
324 if (bandwidth_observer_) {
325 bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, rtt,
326 now_ms);
327 }
328 }
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000329 // TODO(mflodman): Do we need to aggregate reports here or can we jut send
330 // what we get? I.e. do we ever get multiple reports bundled into one RTCP
331 // report for VoiceEngine?
332 if (report_blocks.empty())
333 return;
334
335 int fraction_lost_aggregate = 0;
336 int total_number_of_packets = 0;
337
338 // If receiving multiple report blocks, calculate the weighted average based
339 // on the number of packets a report refers to.
340 for (ReportBlockList::const_iterator block_it = report_blocks.begin();
341 block_it != report_blocks.end(); ++block_it) {
342 // Find the previous extended high sequence number for this remote SSRC,
343 // to calculate the number of RTP packets this report refers to. Ignore if
344 // we haven't seen this SSRC before.
345 std::map<uint32_t, uint32_t>::iterator seq_num_it =
346 extended_max_sequence_number_.find(block_it->sourceSSRC);
347 int number_of_packets = 0;
348 if (seq_num_it != extended_max_sequence_number_.end()) {
349 number_of_packets = block_it->extendedHighSeqNum - seq_num_it->second;
350 }
351 fraction_lost_aggregate += number_of_packets * block_it->fractionLost;
352 total_number_of_packets += number_of_packets;
353
354 extended_max_sequence_number_[block_it->sourceSSRC] =
355 block_it->extendedHighSeqNum;
356 }
357 int weighted_fraction_lost = 0;
358 if (total_number_of_packets > 0) {
kwiberg55b97fe2016-01-28 05:22:45 -0800359 weighted_fraction_lost =
360 (fraction_lost_aggregate + total_number_of_packets / 2) /
361 total_number_of_packets;
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000362 }
363 owner_->OnIncomingFractionLoss(weighted_fraction_lost);
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000364 }
365
366 private:
367 Channel* owner_;
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000368 // Maps remote side ssrc to extended highest sequence number received.
369 std::map<uint32_t, uint32_t> extended_max_sequence_number_;
stefan7de8d642017-02-07 07:14:08 -0800370 rtc::CriticalSection crit_;
371 RtcpBandwidthObserver* bandwidth_observer_ GUARDED_BY(crit_);
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000372};
373
kwiberg55b97fe2016-01-28 05:22:45 -0800374int32_t Channel::SendData(FrameType frameType,
375 uint8_t payloadType,
376 uint32_t timeStamp,
377 const uint8_t* payloadData,
378 size_t payloadSize,
379 const RTPFragmentationHeader* fragmentation) {
380 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
381 "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u,"
382 " payloadSize=%" PRIuS ", fragmentation=0x%x)",
383 frameType, payloadType, timeStamp, payloadSize, fragmentation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000384
kwiberg55b97fe2016-01-28 05:22:45 -0800385 if (_includeAudioLevelIndication) {
386 // Store current audio level in the RTP/RTCP module.
387 // The level will be used in combination with voice-activity state
388 // (frameType) to add an RTP header extension
henrik.lundin50499422016-11-29 04:26:24 -0800389 _rtpRtcpModule->SetAudioLevel(rms_level_.Average());
kwiberg55b97fe2016-01-28 05:22:45 -0800390 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000391
kwiberg55b97fe2016-01-28 05:22:45 -0800392 // Push data from ACM to RTP/RTCP-module to deliver audio frame for
393 // packetization.
394 // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700395 if (!_rtpRtcpModule->SendOutgoingData(
kwiberg55b97fe2016-01-28 05:22:45 -0800396 (FrameType&)frameType, payloadType, timeStamp,
397 // Leaving the time when this frame was
398 // received from the capture device as
399 // undefined for voice for now.
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700400 -1, payloadData, payloadSize, fragmentation, nullptr, nullptr)) {
kwiberg55b97fe2016-01-28 05:22:45 -0800401 _engineStatisticsPtr->SetLastError(
402 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
403 "Channel::SendData() failed to send data to RTP/RTCP module");
404 return -1;
405 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
kwiberg55b97fe2016-01-28 05:22:45 -0800407 _lastLocalTimeStamp = timeStamp;
408 _lastPayloadType = payloadType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000409
kwiberg55b97fe2016-01-28 05:22:45 -0800410 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000411}
412
kwiberg55b97fe2016-01-28 05:22:45 -0800413int32_t Channel::InFrameType(FrameType frame_type) {
414 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
415 "Channel::InFrameType(frame_type=%d)", frame_type);
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
kwiberg55b97fe2016-01-28 05:22:45 -0800417 rtc::CritScope cs(&_callbackCritSect);
418 _sendFrameType = (frame_type == kAudioFrameSpeech);
419 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000420}
421
stefan1d8a5062015-10-02 03:39:33 -0700422bool Channel::SendRtp(const uint8_t* data,
423 size_t len,
424 const PacketOptions& options) {
kwiberg55b97fe2016-01-28 05:22:45 -0800425 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
426 "Channel::SendPacket(channel=%d, len=%" PRIuS ")", len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000427
kwiberg55b97fe2016-01-28 05:22:45 -0800428 rtc::CritScope cs(&_callbackCritSect);
wu@webrtc.orgfb648da2013-10-18 21:10:51 +0000429
kwiberg55b97fe2016-01-28 05:22:45 -0800430 if (_transportPtr == NULL) {
431 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
432 "Channel::SendPacket() failed to send RTP packet due to"
433 " invalid transport object");
434 return false;
435 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000436
kwiberg55b97fe2016-01-28 05:22:45 -0800437 uint8_t* bufferToSendPtr = (uint8_t*)data;
438 size_t bufferLength = len;
niklase@google.com470e71d2011-07-07 08:21:25 +0000439
kwiberg55b97fe2016-01-28 05:22:45 -0800440 if (!_transportPtr->SendRtp(bufferToSendPtr, bufferLength, options)) {
441 std::string transport_name =
442 _externalTransport ? "external transport" : "WebRtc sockets";
443 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
444 "Channel::SendPacket() RTP transmission using %s failed",
445 transport_name.c_str());
446 return false;
447 }
448 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000449}
450
kwiberg55b97fe2016-01-28 05:22:45 -0800451bool Channel::SendRtcp(const uint8_t* data, size_t len) {
452 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
453 "Channel::SendRtcp(len=%" PRIuS ")", len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000454
kwiberg55b97fe2016-01-28 05:22:45 -0800455 rtc::CritScope cs(&_callbackCritSect);
456 if (_transportPtr == NULL) {
457 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
458 "Channel::SendRtcp() failed to send RTCP packet"
459 " due to invalid transport object");
460 return false;
461 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000462
kwiberg55b97fe2016-01-28 05:22:45 -0800463 uint8_t* bufferToSendPtr = (uint8_t*)data;
464 size_t bufferLength = len;
niklase@google.com470e71d2011-07-07 08:21:25 +0000465
kwiberg55b97fe2016-01-28 05:22:45 -0800466 int n = _transportPtr->SendRtcp(bufferToSendPtr, bufferLength);
467 if (n < 0) {
468 std::string transport_name =
469 _externalTransport ? "external transport" : "WebRtc sockets";
470 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
471 "Channel::SendRtcp() transmission using %s failed",
472 transport_name.c_str());
473 return false;
474 }
475 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000476}
477
kwiberg55b97fe2016-01-28 05:22:45 -0800478void Channel::OnIncomingSSRCChanged(uint32_t ssrc) {
479 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
480 "Channel::OnIncomingSSRCChanged(SSRC=%d)", ssrc);
niklase@google.com470e71d2011-07-07 08:21:25 +0000481
kwiberg55b97fe2016-01-28 05:22:45 -0800482 // Update ssrc so that NTP for AV sync can be updated.
483 _rtpRtcpModule->SetRemoteSSRC(ssrc);
niklase@google.com470e71d2011-07-07 08:21:25 +0000484}
485
Peter Boströmac547a62015-09-17 23:03:57 +0200486void Channel::OnIncomingCSRCChanged(uint32_t CSRC, bool added) {
487 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
488 "Channel::OnIncomingCSRCChanged(CSRC=%d, added=%d)", CSRC,
489 added);
niklase@google.com470e71d2011-07-07 08:21:25 +0000490}
491
Peter Boströmac547a62015-09-17 23:03:57 +0200492int32_t Channel::OnInitializeDecoder(
pbos@webrtc.org92135212013-05-14 08:31:39 +0000493 int8_t payloadType,
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +0000494 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
pbos@webrtc.org92135212013-05-14 08:31:39 +0000495 int frequency,
Peter Kasting69558702016-01-12 16:26:35 -0800496 size_t channels,
Peter Boströmac547a62015-09-17 23:03:57 +0200497 uint32_t rate) {
kwiberg55b97fe2016-01-28 05:22:45 -0800498 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
499 "Channel::OnInitializeDecoder(payloadType=%d, "
500 "payloadName=%s, frequency=%u, channels=%" PRIuS ", rate=%u)",
501 payloadType, payloadName, frequency, channels, rate);
niklase@google.com470e71d2011-07-07 08:21:25 +0000502
kwiberg55b97fe2016-01-28 05:22:45 -0800503 CodecInst receiveCodec = {0};
504 CodecInst dummyCodec = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +0000505
kwiberg55b97fe2016-01-28 05:22:45 -0800506 receiveCodec.pltype = payloadType;
507 receiveCodec.plfreq = frequency;
508 receiveCodec.channels = channels;
509 receiveCodec.rate = rate;
510 strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +0000511
kwiberg55b97fe2016-01-28 05:22:45 -0800512 audio_coding_->Codec(payloadName, &dummyCodec, frequency, channels);
513 receiveCodec.pacsize = dummyCodec.pacsize;
niklase@google.com470e71d2011-07-07 08:21:25 +0000514
kwiberg55b97fe2016-01-28 05:22:45 -0800515 // Register the new codec to the ACM
kwibergda2bf4e2016-10-24 13:47:09 -0700516 if (!audio_coding_->RegisterReceiveCodec(receiveCodec.pltype,
517 CodecInstToSdp(receiveCodec))) {
kwiberg55b97fe2016-01-28 05:22:45 -0800518 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
519 "Channel::OnInitializeDecoder() invalid codec ("
520 "pt=%d, name=%s) received - 1",
521 payloadType, payloadName);
522 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR);
523 return -1;
524 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000525
kwiberg55b97fe2016-01-28 05:22:45 -0800526 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000527}
528
kwiberg55b97fe2016-01-28 05:22:45 -0800529int32_t Channel::OnReceivedPayloadData(const uint8_t* payloadData,
530 size_t payloadSize,
531 const WebRtcRTPHeader* rtpHeader) {
532 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
533 "Channel::OnReceivedPayloadData(payloadSize=%" PRIuS
534 ","
535 " payloadType=%u, audioChannel=%" PRIuS ")",
536 payloadSize, rtpHeader->header.payloadType,
537 rtpHeader->type.Audio.channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000538
kwiberg55b97fe2016-01-28 05:22:45 -0800539 if (!channel_state_.Get().playing) {
540 // Avoid inserting into NetEQ when we are not playing. Count the
541 // packet as discarded.
542 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
543 "received packet is discarded since playing is not"
544 " activated");
niklase@google.com470e71d2011-07-07 08:21:25 +0000545 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -0800546 }
547
548 // Push the incoming payload (parsed and ready for decoding) into the ACM
549 if (audio_coding_->IncomingPacket(payloadData, payloadSize, *rtpHeader) !=
550 0) {
551 _engineStatisticsPtr->SetLastError(
552 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
553 "Channel::OnReceivedPayloadData() unable to push data to the ACM");
554 return -1;
555 }
556
kwiberg55b97fe2016-01-28 05:22:45 -0800557 int64_t round_trip_time = 0;
558 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), &round_trip_time, NULL, NULL,
559 NULL);
560
561 std::vector<uint16_t> nack_list = audio_coding_->GetNackList(round_trip_time);
562 if (!nack_list.empty()) {
563 // Can't use nack_list.data() since it's not supported by all
564 // compilers.
565 ResendPackets(&(nack_list[0]), static_cast<int>(nack_list.size()));
566 }
567 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000568}
569
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000570bool Channel::OnRecoveredPacket(const uint8_t* rtp_packet,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000571 size_t rtp_packet_length) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000572 RTPHeader header;
573 if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
574 WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVoice, _channelId,
575 "IncomingPacket invalid RTP header");
576 return false;
577 }
578 header.payload_type_frequency =
579 rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
580 if (header.payload_type_frequency < 0)
581 return false;
582 return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
583}
584
henrik.lundin42dda502016-05-18 05:36:01 -0700585MixerParticipant::AudioFrameInfo Channel::GetAudioFrameWithMuted(
586 int32_t id,
587 AudioFrame* audioFrame) {
ivoc14d5dbe2016-07-04 07:06:55 -0700588 unsigned int ssrc;
nisse7d59f6b2017-02-21 03:40:24 -0800589 RTC_CHECK_EQ(GetRemoteSSRC(ssrc), 0);
ivoc14d5dbe2016-07-04 07:06:55 -0700590 event_log_proxy_->LogAudioPlayout(ssrc);
kwiberg55b97fe2016-01-28 05:22:45 -0800591 // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
henrik.lundind4ccb002016-05-17 12:21:55 -0700592 bool muted;
593 if (audio_coding_->PlayoutData10Ms(audioFrame->sample_rate_hz_, audioFrame,
594 &muted) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -0800595 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
596 "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
597 // In all likelihood, the audio in this frame is garbage. We return an
598 // error so that the audio mixer module doesn't add it to the mix. As
599 // a result, it won't be played out and the actions skipped here are
600 // irrelevant.
henrik.lundin42dda502016-05-18 05:36:01 -0700601 return MixerParticipant::AudioFrameInfo::kError;
kwiberg55b97fe2016-01-28 05:22:45 -0800602 }
henrik.lundina89ab962016-05-18 08:52:45 -0700603
604 if (muted) {
605 // TODO(henrik.lundin): We should be able to do better than this. But we
606 // will have to go through all the cases below where the audio samples may
607 // be used, and handle the muted case in some way.
aleloi6321b492016-12-05 01:46:09 -0800608 AudioFrameOperations::Mute(audioFrame);
henrik.lundina89ab962016-05-18 08:52:45 -0700609 }
kwiberg55b97fe2016-01-28 05:22:45 -0800610
kwiberg55b97fe2016-01-28 05:22:45 -0800611 // Convert module ID to internal VoE channel ID
612 audioFrame->id_ = VoEChannelId(audioFrame->id_);
613 // Store speech type for dead-or-alive detection
614 _outputSpeechType = audioFrame->speech_type_;
615
616 ChannelState::State state = channel_state_.Get();
617
kwiberg55b97fe2016-01-28 05:22:45 -0800618 {
619 // Pass the audio buffers to an optional sink callback, before applying
620 // scaling/panning, as that applies to the mix operation.
621 // External recipients of the audio (e.g. via AudioTrack), will do their
622 // own mixing/dynamic processing.
623 rtc::CritScope cs(&_callbackCritSect);
624 if (audio_sink_) {
625 AudioSinkInterface::Data data(
626 &audioFrame->data_[0], audioFrame->samples_per_channel_,
627 audioFrame->sample_rate_hz_, audioFrame->num_channels_,
628 audioFrame->timestamp_);
629 audio_sink_->OnData(data);
630 }
631 }
632
633 float output_gain = 1.0f;
634 float left_pan = 1.0f;
635 float right_pan = 1.0f;
636 {
637 rtc::CritScope cs(&volume_settings_critsect_);
638 output_gain = _outputGain;
639 left_pan = _panLeft;
640 right_pan = _panRight;
641 }
642
643 // Output volume scaling
644 if (output_gain < 0.99f || output_gain > 1.01f) {
645 AudioFrameOperations::ScaleWithSat(output_gain, *audioFrame);
646 }
647
648 // Scale left and/or right channel(s) if stereo and master balance is
649 // active
650
651 if (left_pan != 1.0f || right_pan != 1.0f) {
652 if (audioFrame->num_channels_ == 1) {
653 // Emulate stereo mode since panning is active.
654 // The mono signal is copied to both left and right channels here.
655 AudioFrameOperations::MonoToStereo(audioFrame);
656 }
657 // For true stereo mode (when we are receiving a stereo signal), no
658 // action is needed.
659
660 // Do the panning operation (the audio frame contains stereo at this
661 // stage)
662 AudioFrameOperations::Scale(left_pan, right_pan, *audioFrame);
663 }
664
665 // Mix decoded PCM output with file if file mixing is enabled
666 if (state.output_file_playing) {
667 MixAudioWithFile(*audioFrame, audioFrame->sample_rate_hz_);
henrik.lundina89ab962016-05-18 08:52:45 -0700668 muted = false; // We may have added non-zero samples.
kwiberg55b97fe2016-01-28 05:22:45 -0800669 }
670
kwiberg55b97fe2016-01-28 05:22:45 -0800671 // Record playout if enabled
672 {
673 rtc::CritScope cs(&_fileCritSect);
674
kwiberg5a25d952016-08-17 07:31:12 -0700675 if (_outputFileRecording && output_file_recorder_) {
676 output_file_recorder_->RecordAudioToFile(*audioFrame);
kwiberg55b97fe2016-01-28 05:22:45 -0800677 }
678 }
679
680 // Measure audio level (0-9)
henrik.lundina89ab962016-05-18 08:52:45 -0700681 // TODO(henrik.lundin) Use the |muted| information here too.
kwiberg55b97fe2016-01-28 05:22:45 -0800682 _outputAudioLevel.ComputeLevel(*audioFrame);
683
684 if (capture_start_rtp_time_stamp_ < 0 && audioFrame->timestamp_ != 0) {
685 // The first frame with a valid rtp timestamp.
686 capture_start_rtp_time_stamp_ = audioFrame->timestamp_;
687 }
688
689 if (capture_start_rtp_time_stamp_ >= 0) {
690 // audioFrame.timestamp_ should be valid from now on.
691
692 // Compute elapsed time.
693 int64_t unwrap_timestamp =
694 rtp_ts_wraparound_handler_->Unwrap(audioFrame->timestamp_);
695 audioFrame->elapsed_time_ms_ =
696 (unwrap_timestamp - capture_start_rtp_time_stamp_) /
ossue280cde2016-10-12 11:04:10 -0700697 (GetRtpTimestampRateHz() / 1000);
kwiberg55b97fe2016-01-28 05:22:45 -0800698
niklase@google.com470e71d2011-07-07 08:21:25 +0000699 {
kwiberg55b97fe2016-01-28 05:22:45 -0800700 rtc::CritScope lock(&ts_stats_lock_);
701 // Compute ntp time.
702 audioFrame->ntp_time_ms_ =
703 ntp_estimator_.Estimate(audioFrame->timestamp_);
704 // |ntp_time_ms_| won't be valid until at least 2 RTCP SRs are received.
705 if (audioFrame->ntp_time_ms_ > 0) {
706 // Compute |capture_start_ntp_time_ms_| so that
707 // |capture_start_ntp_time_ms_| + |elapsed_time_ms_| == |ntp_time_ms_|
708 capture_start_ntp_time_ms_ =
709 audioFrame->ntp_time_ms_ - audioFrame->elapsed_time_ms_;
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000710 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000711 }
kwiberg55b97fe2016-01-28 05:22:45 -0800712 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000713
henrik.lundin42dda502016-05-18 05:36:01 -0700714 return muted ? MixerParticipant::AudioFrameInfo::kMuted
715 : MixerParticipant::AudioFrameInfo::kNormal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000716}
717
aleloi6c278492016-10-20 14:24:39 -0700718AudioMixer::Source::AudioFrameInfo Channel::GetAudioFrameWithInfo(
719 int sample_rate_hz,
720 AudioFrame* audio_frame) {
721 audio_frame->sample_rate_hz_ = sample_rate_hz;
aleloiaed581a2016-10-20 06:32:39 -0700722
aleloi6c278492016-10-20 14:24:39 -0700723 const auto frame_info = GetAudioFrameWithMuted(-1, audio_frame);
aleloiaed581a2016-10-20 06:32:39 -0700724
725 using FrameInfo = AudioMixer::Source::AudioFrameInfo;
726 FrameInfo new_audio_frame_info = FrameInfo::kError;
727 switch (frame_info) {
728 case MixerParticipant::AudioFrameInfo::kNormal:
729 new_audio_frame_info = FrameInfo::kNormal;
730 break;
731 case MixerParticipant::AudioFrameInfo::kMuted:
732 new_audio_frame_info = FrameInfo::kMuted;
733 break;
734 case MixerParticipant::AudioFrameInfo::kError:
735 new_audio_frame_info = FrameInfo::kError;
736 break;
737 }
aleloi6c278492016-10-20 14:24:39 -0700738 return new_audio_frame_info;
aleloiaed581a2016-10-20 06:32:39 -0700739}
740
kwiberg55b97fe2016-01-28 05:22:45 -0800741int32_t Channel::NeededFrequency(int32_t id) const {
742 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
743 "Channel::NeededFrequency(id=%d)", id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000744
kwiberg55b97fe2016-01-28 05:22:45 -0800745 int highestNeeded = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000746
kwiberg55b97fe2016-01-28 05:22:45 -0800747 // Determine highest needed receive frequency
748 int32_t receiveFrequency = audio_coding_->ReceiveFrequency();
niklase@google.com470e71d2011-07-07 08:21:25 +0000749
kwiberg55b97fe2016-01-28 05:22:45 -0800750 // Return the bigger of playout and receive frequency in the ACM.
751 if (audio_coding_->PlayoutFrequency() > receiveFrequency) {
752 highestNeeded = audio_coding_->PlayoutFrequency();
753 } else {
754 highestNeeded = receiveFrequency;
755 }
756
757 // Special case, if we're playing a file on the playout side
758 // we take that frequency into consideration as well
759 // This is not needed on sending side, since the codec will
760 // limit the spectrum anyway.
761 if (channel_state_.Get().output_file_playing) {
762 rtc::CritScope cs(&_fileCritSect);
kwiberg5a25d952016-08-17 07:31:12 -0700763 if (output_file_player_) {
764 if (output_file_player_->Frequency() > highestNeeded) {
765 highestNeeded = output_file_player_->Frequency();
kwiberg55b97fe2016-01-28 05:22:45 -0800766 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000767 }
kwiberg55b97fe2016-01-28 05:22:45 -0800768 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000769
kwiberg55b97fe2016-01-28 05:22:45 -0800770 return (highestNeeded);
niklase@google.com470e71d2011-07-07 08:21:25 +0000771}
772
ossu5f7cfa52016-05-30 08:11:28 -0700773int32_t Channel::CreateChannel(
774 Channel*& channel,
775 int32_t channelId,
776 uint32_t instanceId,
solenberg88499ec2016-09-07 07:34:41 -0700777 const VoEBase::ChannelConfig& config) {
kwiberg55b97fe2016-01-28 05:22:45 -0800778 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId, channelId),
779 "Channel::CreateChannel(channelId=%d, instanceId=%d)", channelId,
780 instanceId);
niklase@google.com470e71d2011-07-07 08:21:25 +0000781
solenberg88499ec2016-09-07 07:34:41 -0700782 channel = new Channel(channelId, instanceId, config);
kwiberg55b97fe2016-01-28 05:22:45 -0800783 if (channel == NULL) {
784 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId, channelId),
785 "Channel::CreateChannel() unable to allocate memory for"
786 " channel");
787 return -1;
788 }
789 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000790}
791
kwiberg55b97fe2016-01-28 05:22:45 -0800792void Channel::PlayNotification(int32_t id, uint32_t durationMs) {
793 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
794 "Channel::PlayNotification(id=%d, durationMs=%d)", id,
795 durationMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000796
kwiberg55b97fe2016-01-28 05:22:45 -0800797 // Not implement yet
niklase@google.com470e71d2011-07-07 08:21:25 +0000798}
799
kwiberg55b97fe2016-01-28 05:22:45 -0800800void Channel::RecordNotification(int32_t id, uint32_t durationMs) {
801 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
802 "Channel::RecordNotification(id=%d, durationMs=%d)", id,
803 durationMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000804
kwiberg55b97fe2016-01-28 05:22:45 -0800805 // Not implement yet
niklase@google.com470e71d2011-07-07 08:21:25 +0000806}
807
kwiberg55b97fe2016-01-28 05:22:45 -0800808void Channel::PlayFileEnded(int32_t id) {
809 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
810 "Channel::PlayFileEnded(id=%d)", id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000811
kwiberg55b97fe2016-01-28 05:22:45 -0800812 if (id == _inputFilePlayerId) {
813 channel_state_.SetInputFilePlaying(false);
814 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
815 "Channel::PlayFileEnded() => input file player module is"
niklase@google.com470e71d2011-07-07 08:21:25 +0000816 " shutdown");
kwiberg55b97fe2016-01-28 05:22:45 -0800817 } else if (id == _outputFilePlayerId) {
818 channel_state_.SetOutputFilePlaying(false);
819 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
820 "Channel::PlayFileEnded() => output file player module is"
821 " shutdown");
822 }
823}
824
825void Channel::RecordFileEnded(int32_t id) {
826 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
827 "Channel::RecordFileEnded(id=%d)", id);
828
829 assert(id == _outputFileRecorderId);
830
831 rtc::CritScope cs(&_fileCritSect);
832
833 _outputFileRecording = false;
834 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
835 "Channel::RecordFileEnded() => output file recorder module is"
836 " shutdown");
niklase@google.com470e71d2011-07-07 08:21:25 +0000837}
838
pbos@webrtc.org92135212013-05-14 08:31:39 +0000839Channel::Channel(int32_t channelId,
minyue@webrtc.orge509f942013-09-12 17:03:00 +0000840 uint32_t instanceId,
solenberg88499ec2016-09-07 07:34:41 -0700841 const VoEBase::ChannelConfig& config)
tommi31fc21f2016-01-21 10:37:37 -0800842 : _instanceId(instanceId),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100843 _channelId(channelId),
ivoc14d5dbe2016-07-04 07:06:55 -0700844 event_log_proxy_(new RtcEventLogProxy()),
michaelt9332b7d2016-11-30 07:51:13 -0800845 rtcp_rtt_stats_proxy_(new RtcpRttStatsProxy()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100846 rtp_header_parser_(RtpHeaderParser::Create()),
magjedf3feeff2016-11-25 06:40:25 -0800847 rtp_payload_registry_(new RTPPayloadRegistry()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100848 rtp_receive_statistics_(
849 ReceiveStatistics::Create(Clock::GetRealTimeClock())),
850 rtp_receiver_(
851 RtpReceiver::CreateAudioReceiver(Clock::GetRealTimeClock(),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100852 this,
853 this,
854 rtp_payload_registry_.get())),
danilchap799a9d02016-09-22 03:36:27 -0700855 telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100856 _outputAudioLevel(),
857 _externalTransport(false),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100858 // Avoid conflict with other channels by adding 1024 - 1026,
859 // won't use as much as 1024 channels.
860 _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
861 _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
862 _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
863 _outputFileRecording(false),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100864 _timeStamp(0), // This is just an offset, RTP module will add it's own
865 // random offset
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100866 ntp_estimator_(Clock::GetRealTimeClock()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100867 playout_timestamp_rtp_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100868 playout_delay_ms_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100869 send_sequence_number_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100870 rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()),
871 capture_start_rtp_time_stamp_(-1),
872 capture_start_ntp_time_ms_(-1),
873 _engineStatisticsPtr(NULL),
874 _outputMixerPtr(NULL),
875 _transmitMixerPtr(NULL),
876 _moduleProcessThreadPtr(NULL),
877 _audioDeviceModulePtr(NULL),
878 _voiceEngineObserverPtr(NULL),
879 _callbackCritSectPtr(NULL),
880 _transportPtr(NULL),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100881 _sendFrameType(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100882 _mixFileWithMicrophone(false),
solenberg1c2af8e2016-03-24 10:36:00 -0700883 input_mute_(false),
884 previous_frame_muted_(false),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100885 _panLeft(1.0f),
886 _panRight(1.0f),
887 _outputGain(1.0f),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100888 _lastLocalTimeStamp(0),
889 _lastPayloadType(0),
890 _includeAudioLevelIndication(false),
nisse284542b2017-01-10 08:58:32 -0800891 transport_overhead_per_packet_(0),
892 rtp_overhead_per_packet_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100893 _outputSpeechType(AudioFrame::kNormalSpeech),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100894 restored_packet_in_use_(false),
895 rtcp_observer_(new VoERtcpObserver(this)),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100896 associate_send_channel_(ChannelOwner(nullptr)),
solenberg88499ec2016-09-07 07:34:41 -0700897 pacing_enabled_(config.enable_voice_pacing),
stefanbba9dec2016-02-01 04:39:55 -0800898 feedback_observer_proxy_(new TransportFeedbackProxy()),
899 seq_num_allocator_proxy_(new TransportSequenceNumberProxy()),
ossu29b1a8d2016-06-13 07:34:51 -0700900 rtp_packet_sender_proxy_(new RtpPacketSenderProxy()),
Erik Språng737336d2016-07-29 12:59:36 +0200901 retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(),
902 kMaxRetransmissionWindowMs)),
michaelt566d8202017-01-12 10:17:38 -0800903 decoder_factory_(config.acm_config.decoder_factory) {
kwiberg55b97fe2016-01-28 05:22:45 -0800904 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, _channelId),
905 "Channel::Channel() - ctor");
solenberg88499ec2016-09-07 07:34:41 -0700906 AudioCodingModule::Config acm_config(config.acm_config);
kwiberg55b97fe2016-01-28 05:22:45 -0800907 acm_config.id = VoEModuleId(instanceId, channelId);
henrik.lundina89ab962016-05-18 08:52:45 -0700908 acm_config.neteq_config.enable_muted_state = true;
kwiberg55b97fe2016-01-28 05:22:45 -0800909 audio_coding_.reset(AudioCodingModule::Create(acm_config));
Henrik Lundin64dad832015-05-11 12:44:23 +0200910
kwiberg55b97fe2016-01-28 05:22:45 -0800911 _outputAudioLevel.Clear();
niklase@google.com470e71d2011-07-07 08:21:25 +0000912
kwiberg55b97fe2016-01-28 05:22:45 -0800913 RtpRtcp::Configuration configuration;
914 configuration.audio = true;
915 configuration.outgoing_transport = this;
michaeltbf65be52016-12-15 06:24:49 -0800916 configuration.overhead_observer = this;
kwiberg55b97fe2016-01-28 05:22:45 -0800917 configuration.receive_statistics = rtp_receive_statistics_.get();
918 configuration.bandwidth_callback = rtcp_observer_.get();
stefanbba9dec2016-02-01 04:39:55 -0800919 if (pacing_enabled_) {
920 configuration.paced_sender = rtp_packet_sender_proxy_.get();
921 configuration.transport_sequence_number_allocator =
922 seq_num_allocator_proxy_.get();
923 configuration.transport_feedback_callback = feedback_observer_proxy_.get();
924 }
ivoc14d5dbe2016-07-04 07:06:55 -0700925 configuration.event_log = &(*event_log_proxy_);
michaelt9332b7d2016-11-30 07:51:13 -0800926 configuration.rtt_stats = &(*rtcp_rtt_stats_proxy_);
Erik Språng737336d2016-07-29 12:59:36 +0200927 configuration.retransmission_rate_limiter =
928 retransmission_rate_limiter_.get();
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000929
kwiberg55b97fe2016-01-28 05:22:45 -0800930 _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
Peter Boström3dd5d1d2016-02-25 16:56:48 +0100931 _rtpRtcpModule->SetSendingMediaStatus(false);
niklase@google.com470e71d2011-07-07 08:21:25 +0000932}
933
kwiberg55b97fe2016-01-28 05:22:45 -0800934Channel::~Channel() {
935 rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL);
936 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, _channelId),
937 "Channel::~Channel() - dtor");
niklase@google.com470e71d2011-07-07 08:21:25 +0000938
kwiberg55b97fe2016-01-28 05:22:45 -0800939 StopSend();
940 StopPlayout();
niklase@google.com470e71d2011-07-07 08:21:25 +0000941
kwiberg55b97fe2016-01-28 05:22:45 -0800942 {
943 rtc::CritScope cs(&_fileCritSect);
kwiberg5a25d952016-08-17 07:31:12 -0700944 if (input_file_player_) {
945 input_file_player_->RegisterModuleFileCallback(NULL);
946 input_file_player_->StopPlayingFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000947 }
kwiberg5a25d952016-08-17 07:31:12 -0700948 if (output_file_player_) {
949 output_file_player_->RegisterModuleFileCallback(NULL);
950 output_file_player_->StopPlayingFile();
kwiberg55b97fe2016-01-28 05:22:45 -0800951 }
kwiberg5a25d952016-08-17 07:31:12 -0700952 if (output_file_recorder_) {
953 output_file_recorder_->RegisterModuleFileCallback(NULL);
954 output_file_recorder_->StopRecording();
kwiberg55b97fe2016-01-28 05:22:45 -0800955 }
956 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000957
kwiberg55b97fe2016-01-28 05:22:45 -0800958 // The order to safely shutdown modules in a channel is:
959 // 1. De-register callbacks in modules
960 // 2. De-register modules in process thread
961 // 3. Destroy modules
962 if (audio_coding_->RegisterTransportCallback(NULL) == -1) {
963 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
964 "~Channel() failed to de-register transport callback"
965 " (Audio coding module)");
966 }
967 if (audio_coding_->RegisterVADCallback(NULL) == -1) {
968 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
969 "~Channel() failed to de-register VAD callback"
970 " (Audio coding module)");
971 }
972 // De-register modules in process thread
973 _moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get());
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000974
kwiberg55b97fe2016-01-28 05:22:45 -0800975 // End of modules shutdown
niklase@google.com470e71d2011-07-07 08:21:25 +0000976}
977
kwiberg55b97fe2016-01-28 05:22:45 -0800978int32_t Channel::Init() {
979 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
980 "Channel::Init()");
niklase@google.com470e71d2011-07-07 08:21:25 +0000981
kwiberg55b97fe2016-01-28 05:22:45 -0800982 channel_state_.Reset();
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +0000983
kwiberg55b97fe2016-01-28 05:22:45 -0800984 // --- Initial sanity
niklase@google.com470e71d2011-07-07 08:21:25 +0000985
kwiberg55b97fe2016-01-28 05:22:45 -0800986 if ((_engineStatisticsPtr == NULL) || (_moduleProcessThreadPtr == NULL)) {
987 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
988 "Channel::Init() must call SetEngineInformation() first");
989 return -1;
990 }
991
992 // --- Add modules to process thread (for periodic schedulation)
993
994 _moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get());
995
996 // --- ACM initialization
997
998 if (audio_coding_->InitializeReceiver() == -1) {
999 _engineStatisticsPtr->SetLastError(
1000 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1001 "Channel::Init() unable to initialize the ACM - 1");
1002 return -1;
1003 }
1004
1005 // --- RTP/RTCP module initialization
1006
1007 // Ensure that RTCP is enabled by default for the created channel.
1008 // Note that, the module will keep generating RTCP until it is explicitly
1009 // disabled by the user.
1010 // After StopListen (when no sockets exists), RTCP packets will no longer
1011 // be transmitted since the Transport object will then be invalid.
danilchap799a9d02016-09-22 03:36:27 -07001012 telephone_event_handler_->SetTelephoneEventForwardToDecoder(true);
kwiberg55b97fe2016-01-28 05:22:45 -08001013 // RTCP is enabled by default.
1014 _rtpRtcpModule->SetRTCPStatus(RtcpMode::kCompound);
1015 // --- Register all permanent callbacks
1016 const bool fail = (audio_coding_->RegisterTransportCallback(this) == -1) ||
1017 (audio_coding_->RegisterVADCallback(this) == -1);
1018
1019 if (fail) {
1020 _engineStatisticsPtr->SetLastError(
1021 VE_CANNOT_INIT_CHANNEL, kTraceError,
1022 "Channel::Init() callbacks not registered");
1023 return -1;
1024 }
1025
1026 // --- Register all supported codecs to the receiving side of the
1027 // RTP/RTCP module
1028
1029 CodecInst codec;
1030 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
1031
1032 for (int idx = 0; idx < nSupportedCodecs; idx++) {
1033 // Open up the RTP/RTCP receiver for all supported codecs
1034 if ((audio_coding_->Codec(idx, &codec) == -1) ||
magjed56124bd2016-11-24 09:34:46 -08001035 (rtp_receiver_->RegisterReceivePayload(codec) == -1)) {
kwiberg55b97fe2016-01-28 05:22:45 -08001036 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1037 "Channel::Init() unable to register %s "
1038 "(%d/%d/%" PRIuS "/%d) to RTP/RTCP receiver",
1039 codec.plname, codec.pltype, codec.plfreq, codec.channels,
1040 codec.rate);
1041 } else {
1042 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1043 "Channel::Init() %s (%d/%d/%" PRIuS
1044 "/%d) has been "
1045 "added to the RTP/RTCP receiver",
1046 codec.plname, codec.pltype, codec.plfreq, codec.channels,
1047 codec.rate);
niklase@google.com470e71d2011-07-07 08:21:25 +00001048 }
1049
kwiberg55b97fe2016-01-28 05:22:45 -08001050 // Ensure that PCMU is used as default codec on the sending side
1051 if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1)) {
1052 SetSendCodec(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +00001053 }
1054
kwiberg55b97fe2016-01-28 05:22:45 -08001055 // Register default PT for outband 'telephone-event'
1056 if (!STR_CASE_CMP(codec.plname, "telephone-event")) {
kwibergc8d071e2016-04-06 12:22:38 -07001057 if (_rtpRtcpModule->RegisterSendPayload(codec) == -1 ||
kwibergda2bf4e2016-10-24 13:47:09 -07001058 !audio_coding_->RegisterReceiveCodec(codec.pltype,
1059 CodecInstToSdp(codec))) {
kwiberg55b97fe2016-01-28 05:22:45 -08001060 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1061 "Channel::Init() failed to register outband "
1062 "'telephone-event' (%d/%d) correctly",
1063 codec.pltype, codec.plfreq);
1064 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001065 }
1066
kwiberg55b97fe2016-01-28 05:22:45 -08001067 if (!STR_CASE_CMP(codec.plname, "CN")) {
kwibergc8d071e2016-04-06 12:22:38 -07001068 if (!codec_manager_.RegisterEncoder(codec) ||
1069 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get()) ||
kwibergda2bf4e2016-10-24 13:47:09 -07001070 !audio_coding_->RegisterReceiveCodec(codec.pltype,
1071 CodecInstToSdp(codec)) ||
kwibergc8d071e2016-04-06 12:22:38 -07001072 _rtpRtcpModule->RegisterSendPayload(codec) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08001073 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1074 "Channel::Init() failed to register CN (%d/%d) "
1075 "correctly - 1",
1076 codec.pltype, codec.plfreq);
1077 }
1078 }
kwiberg55b97fe2016-01-28 05:22:45 -08001079 }
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001080
kwiberg55b97fe2016-01-28 05:22:45 -08001081 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001082}
1083
kwiberg55b97fe2016-01-28 05:22:45 -08001084int32_t Channel::SetEngineInformation(Statistics& engineStatistics,
1085 OutputMixer& outputMixer,
1086 voe::TransmitMixer& transmitMixer,
1087 ProcessThread& moduleProcessThread,
1088 AudioDeviceModule& audioDeviceModule,
1089 VoiceEngineObserver* voiceEngineObserver,
1090 rtc::CriticalSection* callbackCritSect) {
1091 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1092 "Channel::SetEngineInformation()");
1093 _engineStatisticsPtr = &engineStatistics;
1094 _outputMixerPtr = &outputMixer;
1095 _transmitMixerPtr = &transmitMixer,
1096 _moduleProcessThreadPtr = &moduleProcessThread;
1097 _audioDeviceModulePtr = &audioDeviceModule;
1098 _voiceEngineObserverPtr = voiceEngineObserver;
1099 _callbackCritSectPtr = callbackCritSect;
1100 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001101}
1102
kwiberg55b97fe2016-01-28 05:22:45 -08001103int32_t Channel::UpdateLocalTimeStamp() {
1104 _timeStamp += static_cast<uint32_t>(_audioFrame.samples_per_channel_);
1105 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001106}
1107
kwibergb7f89d62016-02-17 10:04:18 -08001108void Channel::SetSink(std::unique_ptr<AudioSinkInterface> sink) {
tommi31fc21f2016-01-21 10:37:37 -08001109 rtc::CritScope cs(&_callbackCritSect);
deadbeef2d110be2016-01-13 12:00:26 -08001110 audio_sink_ = std::move(sink);
Tommif888bb52015-12-12 01:37:01 +01001111}
1112
ossu29b1a8d2016-06-13 07:34:51 -07001113const rtc::scoped_refptr<AudioDecoderFactory>&
1114Channel::GetAudioDecoderFactory() const {
1115 return decoder_factory_;
1116}
1117
kwiberg55b97fe2016-01-28 05:22:45 -08001118int32_t Channel::StartPlayout() {
1119 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1120 "Channel::StartPlayout()");
1121 if (channel_state_.Get().playing) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001122 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001123 }
1124
solenberge374e012017-02-14 04:55:00 -08001125 // Add participant as candidates for mixing.
1126 if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0) {
1127 _engineStatisticsPtr->SetLastError(
1128 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1129 "StartPlayout() failed to add participant to mixer");
1130 return -1;
kwiberg55b97fe2016-01-28 05:22:45 -08001131 }
1132
1133 channel_state_.SetPlaying(true);
1134 if (RegisterFilePlayingToMixer() != 0)
1135 return -1;
1136
1137 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001138}
1139
kwiberg55b97fe2016-01-28 05:22:45 -08001140int32_t Channel::StopPlayout() {
1141 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1142 "Channel::StopPlayout()");
1143 if (!channel_state_.Get().playing) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001144 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001145 }
1146
solenberge374e012017-02-14 04:55:00 -08001147 // Remove participant as candidates for mixing
1148 if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0) {
1149 _engineStatisticsPtr->SetLastError(
1150 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1151 "StopPlayout() failed to remove participant from mixer");
1152 return -1;
kwiberg55b97fe2016-01-28 05:22:45 -08001153 }
1154
1155 channel_state_.SetPlaying(false);
1156 _outputAudioLevel.Clear();
1157
1158 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001159}
1160
kwiberg55b97fe2016-01-28 05:22:45 -08001161int32_t Channel::StartSend() {
1162 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1163 "Channel::StartSend()");
kwiberg55b97fe2016-01-28 05:22:45 -08001164 if (channel_state_.Get().sending) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001165 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001166 }
1167 channel_state_.SetSending(true);
niklase@google.com470e71d2011-07-07 08:21:25 +00001168
solenberg08b19df2017-02-15 00:42:31 -08001169 // Resume the previous sequence number which was reset by StopSend(). This
1170 // needs to be done before |sending| is set to true on the RTP/RTCP module.
1171 if (send_sequence_number_) {
1172 _rtpRtcpModule->SetSequenceNumber(send_sequence_number_);
1173 }
Peter Boström3dd5d1d2016-02-25 16:56:48 +01001174 _rtpRtcpModule->SetSendingMediaStatus(true);
kwiberg55b97fe2016-01-28 05:22:45 -08001175 if (_rtpRtcpModule->SetSendingStatus(true) != 0) {
1176 _engineStatisticsPtr->SetLastError(
1177 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1178 "StartSend() RTP/RTCP failed to start sending");
Peter Boström3dd5d1d2016-02-25 16:56:48 +01001179 _rtpRtcpModule->SetSendingMediaStatus(false);
kwiberg55b97fe2016-01-28 05:22:45 -08001180 rtc::CritScope cs(&_callbackCritSect);
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +00001181 channel_state_.SetSending(false);
kwiberg55b97fe2016-01-28 05:22:45 -08001182 return -1;
1183 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001184
kwiberg55b97fe2016-01-28 05:22:45 -08001185 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001186}
1187
kwiberg55b97fe2016-01-28 05:22:45 -08001188int32_t Channel::StopSend() {
1189 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1190 "Channel::StopSend()");
1191 if (!channel_state_.Get().sending) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001192 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001193 }
1194 channel_state_.SetSending(false);
1195
1196 // Store the sequence number to be able to pick up the same sequence for
1197 // the next StartSend(). This is needed for restarting device, otherwise
1198 // it might cause libSRTP to complain about packets being replayed.
1199 // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring
1200 // CL is landed. See issue
1201 // https://code.google.com/p/webrtc/issues/detail?id=2111 .
1202 send_sequence_number_ = _rtpRtcpModule->SequenceNumber();
1203
1204 // Reset sending SSRC and sequence number and triggers direct transmission
1205 // of RTCP BYE
1206 if (_rtpRtcpModule->SetSendingStatus(false) == -1) {
1207 _engineStatisticsPtr->SetLastError(
1208 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1209 "StartSend() RTP/RTCP failed to stop sending");
1210 }
Peter Boström3dd5d1d2016-02-25 16:56:48 +01001211 _rtpRtcpModule->SetSendingMediaStatus(false);
kwiberg55b97fe2016-01-28 05:22:45 -08001212
1213 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001214}
1215
kwiberg55b97fe2016-01-28 05:22:45 -08001216int32_t Channel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer) {
1217 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1218 "Channel::RegisterVoiceEngineObserver()");
1219 rtc::CritScope cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001220
kwiberg55b97fe2016-01-28 05:22:45 -08001221 if (_voiceEngineObserverPtr) {
1222 _engineStatisticsPtr->SetLastError(
1223 VE_INVALID_OPERATION, kTraceError,
1224 "RegisterVoiceEngineObserver() observer already enabled");
1225 return -1;
1226 }
1227 _voiceEngineObserverPtr = &observer;
1228 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001229}
1230
kwiberg55b97fe2016-01-28 05:22:45 -08001231int32_t Channel::DeRegisterVoiceEngineObserver() {
1232 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1233 "Channel::DeRegisterVoiceEngineObserver()");
1234 rtc::CritScope cs(&_callbackCritSect);
1235
1236 if (!_voiceEngineObserverPtr) {
1237 _engineStatisticsPtr->SetLastError(
1238 VE_INVALID_OPERATION, kTraceWarning,
1239 "DeRegisterVoiceEngineObserver() observer already disabled");
1240 return 0;
1241 }
1242 _voiceEngineObserverPtr = NULL;
1243 return 0;
1244}
1245
1246int32_t Channel::GetSendCodec(CodecInst& codec) {
kwibergc8d071e2016-04-06 12:22:38 -07001247 auto send_codec = codec_manager_.GetCodecInst();
kwiberg1fd4a4a2015-11-03 11:20:50 -08001248 if (send_codec) {
1249 codec = *send_codec;
1250 return 0;
1251 }
1252 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001253}
1254
kwiberg55b97fe2016-01-28 05:22:45 -08001255int32_t Channel::GetRecCodec(CodecInst& codec) {
1256 return (audio_coding_->ReceiveCodec(&codec));
niklase@google.com470e71d2011-07-07 08:21:25 +00001257}
1258
kwiberg55b97fe2016-01-28 05:22:45 -08001259int32_t Channel::SetSendCodec(const CodecInst& codec) {
1260 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1261 "Channel::SetSendCodec()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001262
kwibergc8d071e2016-04-06 12:22:38 -07001263 if (!codec_manager_.RegisterEncoder(codec) ||
1264 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
kwiberg55b97fe2016-01-28 05:22:45 -08001265 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
1266 "SetSendCodec() failed to register codec to ACM");
1267 return -1;
1268 }
1269
1270 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1271 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1272 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1273 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
1274 "SetSendCodec() failed to register codec to"
1275 " RTP/RTCP module");
1276 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001277 }
kwiberg55b97fe2016-01-28 05:22:45 -08001278 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001279
kwiberg55b97fe2016-01-28 05:22:45 -08001280 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001281}
1282
minyue78b4d562016-11-30 04:47:39 -08001283void Channel::SetBitRate(int bitrate_bps, int64_t probing_interval_ms) {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001284 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1285 "Channel::SetBitRate(bitrate_bps=%d)", bitrate_bps);
minyue7e304322016-10-12 05:00:55 -07001286 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
michaelt2fedf9c2016-11-28 02:34:18 -08001287 if (*encoder) {
1288 (*encoder)->OnReceivedUplinkBandwidth(
michaelt566d8202017-01-12 10:17:38 -08001289 bitrate_bps, rtc::Optional<int64_t>(probing_interval_ms));
michaelt2fedf9c2016-11-28 02:34:18 -08001290 }
1291 });
michaelt566d8202017-01-12 10:17:38 -08001292 retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
Ivo Creusenadf89b72015-04-29 16:03:33 +02001293}
1294
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +00001295void Channel::OnIncomingFractionLoss(int fraction_lost) {
minyue7e304322016-10-12 05:00:55 -07001296 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1297 if (*encoder)
1298 (*encoder)->OnReceivedUplinkPacketLossFraction(fraction_lost / 255.0f);
1299 });
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00001300}
1301
kwiberg55b97fe2016-01-28 05:22:45 -08001302int32_t Channel::SetVADStatus(bool enableVAD,
1303 ACMVADMode mode,
1304 bool disableDTX) {
1305 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1306 "Channel::SetVADStatus(mode=%d)", mode);
kwibergc8d071e2016-04-06 12:22:38 -07001307 RTC_DCHECK(!(disableDTX && enableVAD)); // disableDTX mode is deprecated.
1308 if (!codec_manager_.SetVAD(enableVAD, mode) ||
1309 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
kwiberg55b97fe2016-01-28 05:22:45 -08001310 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR,
1311 kTraceError,
1312 "SetVADStatus() failed to set VAD");
1313 return -1;
1314 }
1315 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001316}
1317
kwiberg55b97fe2016-01-28 05:22:45 -08001318int32_t Channel::GetVADStatus(bool& enabledVAD,
1319 ACMVADMode& mode,
1320 bool& disabledDTX) {
kwibergc8d071e2016-04-06 12:22:38 -07001321 const auto* params = codec_manager_.GetStackParams();
1322 enabledVAD = params->use_cng;
1323 mode = params->vad_mode;
1324 disabledDTX = !params->use_cng;
kwiberg55b97fe2016-01-28 05:22:45 -08001325 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001326}
1327
kwiberg55b97fe2016-01-28 05:22:45 -08001328int32_t Channel::SetRecPayloadType(const CodecInst& codec) {
kwibergd32bf752017-01-19 07:03:59 -08001329 return SetRecPayloadType(codec.pltype, CodecInstToSdp(codec));
1330}
1331
1332int32_t Channel::SetRecPayloadType(int payload_type,
1333 const SdpAudioFormat& format) {
kwiberg55b97fe2016-01-28 05:22:45 -08001334 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1335 "Channel::SetRecPayloadType()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001336
kwiberg55b97fe2016-01-28 05:22:45 -08001337 if (channel_state_.Get().playing) {
1338 _engineStatisticsPtr->SetLastError(
1339 VE_ALREADY_PLAYING, kTraceError,
1340 "SetRecPayloadType() unable to set PT while playing");
1341 return -1;
1342 }
kwiberg55b97fe2016-01-28 05:22:45 -08001343
kwibergd32bf752017-01-19 07:03:59 -08001344 const CodecInst codec = [&] {
1345 CodecInst c = SdpToCodecInst(payload_type, format);
1346
1347 // Bug 6986: Emulate an old bug that caused us to always choose to decode
1348 // Opus in stereo. To be able to remove this, we first need to fix the
1349 // other half of bug 6986, which is about losing the Opus "stereo"
1350 // parameter.
1351 // TODO(kwiberg): Remove this special case, a.k.a. fix bug 6986.
1352 if (STR_CASE_CMP(codec.plname, "opus") == 0) {
1353 c.channels = 2;
1354 }
1355
1356 return c;
1357 }();
1358
1359 if (payload_type == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08001360 // De-register the selected codec (RTP/RTCP module and ACM)
1361
1362 int8_t pltype(-1);
1363 CodecInst rxCodec = codec;
1364
1365 // Get payload type for the given codec
magjed56124bd2016-11-24 09:34:46 -08001366 rtp_payload_registry_->ReceivePayloadType(rxCodec, &pltype);
kwiberg55b97fe2016-01-28 05:22:45 -08001367 rxCodec.pltype = pltype;
1368
1369 if (rtp_receiver_->DeRegisterReceivePayload(pltype) != 0) {
1370 _engineStatisticsPtr->SetLastError(
1371 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1372 "SetRecPayloadType() RTP/RTCP-module deregistration "
1373 "failed");
1374 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001375 }
kwiberg55b97fe2016-01-28 05:22:45 -08001376 if (audio_coding_->UnregisterReceiveCodec(rxCodec.pltype) != 0) {
1377 _engineStatisticsPtr->SetLastError(
1378 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1379 "SetRecPayloadType() ACM deregistration failed - 1");
1380 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001381 }
kwiberg55b97fe2016-01-28 05:22:45 -08001382 return 0;
1383 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001384
magjed56124bd2016-11-24 09:34:46 -08001385 if (rtp_receiver_->RegisterReceivePayload(codec) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001386 // First attempt to register failed => de-register and try again
kwibergc8d071e2016-04-06 12:22:38 -07001387 // TODO(kwiberg): Retrying is probably not necessary, since
1388 // AcmReceiver::AddCodec also retries.
kwiberg55b97fe2016-01-28 05:22:45 -08001389 rtp_receiver_->DeRegisterReceivePayload(codec.pltype);
magjed56124bd2016-11-24 09:34:46 -08001390 if (rtp_receiver_->RegisterReceivePayload(codec) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001391 _engineStatisticsPtr->SetLastError(
1392 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1393 "SetRecPayloadType() RTP/RTCP-module registration failed");
1394 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001395 }
kwiberg55b97fe2016-01-28 05:22:45 -08001396 }
kwibergd32bf752017-01-19 07:03:59 -08001397 if (!audio_coding_->RegisterReceiveCodec(payload_type, format)) {
1398 audio_coding_->UnregisterReceiveCodec(payload_type);
1399 if (!audio_coding_->RegisterReceiveCodec(payload_type, format)) {
kwiberg55b97fe2016-01-28 05:22:45 -08001400 _engineStatisticsPtr->SetLastError(
1401 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1402 "SetRecPayloadType() ACM registration failed - 1");
1403 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001404 }
kwiberg55b97fe2016-01-28 05:22:45 -08001405 }
1406 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001407}
1408
kwiberg55b97fe2016-01-28 05:22:45 -08001409int32_t Channel::GetRecPayloadType(CodecInst& codec) {
1410 int8_t payloadType(-1);
magjed56124bd2016-11-24 09:34:46 -08001411 if (rtp_payload_registry_->ReceivePayloadType(codec, &payloadType) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001412 _engineStatisticsPtr->SetLastError(
1413 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1414 "GetRecPayloadType() failed to retrieve RX payload type");
1415 return -1;
1416 }
1417 codec.pltype = payloadType;
1418 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001419}
1420
kwiberg55b97fe2016-01-28 05:22:45 -08001421int32_t Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency) {
1422 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1423 "Channel::SetSendCNPayloadType()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001424
kwiberg55b97fe2016-01-28 05:22:45 -08001425 CodecInst codec;
1426 int32_t samplingFreqHz(-1);
1427 const size_t kMono = 1;
1428 if (frequency == kFreq32000Hz)
1429 samplingFreqHz = 32000;
1430 else if (frequency == kFreq16000Hz)
1431 samplingFreqHz = 16000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001432
kwiberg55b97fe2016-01-28 05:22:45 -08001433 if (audio_coding_->Codec("CN", &codec, samplingFreqHz, kMono) == -1) {
1434 _engineStatisticsPtr->SetLastError(
1435 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1436 "SetSendCNPayloadType() failed to retrieve default CN codec "
1437 "settings");
1438 return -1;
1439 }
1440
1441 // Modify the payload type (must be set to dynamic range)
1442 codec.pltype = type;
1443
kwibergc8d071e2016-04-06 12:22:38 -07001444 if (!codec_manager_.RegisterEncoder(codec) ||
1445 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
kwiberg55b97fe2016-01-28 05:22:45 -08001446 _engineStatisticsPtr->SetLastError(
1447 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1448 "SetSendCNPayloadType() failed to register CN to ACM");
1449 return -1;
1450 }
1451
1452 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1453 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1454 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1455 _engineStatisticsPtr->SetLastError(
1456 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1457 "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
1458 "module");
1459 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001460 }
kwiberg55b97fe2016-01-28 05:22:45 -08001461 }
1462 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001463}
1464
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001465int Channel::SetOpusMaxPlaybackRate(int frequency_hz) {
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001466 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001467 "Channel::SetOpusMaxPlaybackRate()");
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001468
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001469 if (audio_coding_->SetOpusMaxPlaybackRate(frequency_hz) != 0) {
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001470 _engineStatisticsPtr->SetLastError(
1471 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001472 "SetOpusMaxPlaybackRate() failed to set maximum playback rate");
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001473 return -1;
1474 }
1475 return 0;
1476}
1477
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +00001478int Channel::SetOpusDtx(bool enable_dtx) {
1479 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1480 "Channel::SetOpusDtx(%d)", enable_dtx);
Minyue Li092041c2015-05-11 12:19:35 +02001481 int ret = enable_dtx ? audio_coding_->EnableOpusDtx()
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +00001482 : audio_coding_->DisableOpusDtx();
1483 if (ret != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001484 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR,
1485 kTraceError, "SetOpusDtx() failed");
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +00001486 return -1;
1487 }
1488 return 0;
1489}
1490
ivoc85228d62016-07-27 04:53:47 -07001491int Channel::GetOpusDtx(bool* enabled) {
1492 int success = -1;
1493 audio_coding_->QueryEncoder([&](AudioEncoder const* encoder) {
1494 if (encoder) {
1495 *enabled = encoder->GetDtx();
1496 success = 0;
1497 }
1498 });
1499 return success;
1500}
1501
minyue7e304322016-10-12 05:00:55 -07001502bool Channel::EnableAudioNetworkAdaptor(const std::string& config_string) {
1503 bool success = false;
1504 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1505 if (*encoder) {
1506 success = (*encoder)->EnableAudioNetworkAdaptor(
michaeltbf279fc2017-01-13 06:02:29 -08001507 config_string, event_log_proxy_.get(), Clock::GetRealTimeClock());
minyue7e304322016-10-12 05:00:55 -07001508 }
1509 });
1510 return success;
1511}
1512
1513void Channel::DisableAudioNetworkAdaptor() {
1514 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1515 if (*encoder)
1516 (*encoder)->DisableAudioNetworkAdaptor();
1517 });
1518}
1519
1520void Channel::SetReceiverFrameLengthRange(int min_frame_length_ms,
1521 int max_frame_length_ms) {
1522 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1523 if (*encoder) {
1524 (*encoder)->SetReceiverFrameLengthRange(min_frame_length_ms,
1525 max_frame_length_ms);
1526 }
1527 });
1528}
1529
mflodman3d7db262016-04-29 00:57:13 -07001530int32_t Channel::RegisterExternalTransport(Transport* transport) {
kwiberg55b97fe2016-01-28 05:22:45 -08001531 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00001532 "Channel::RegisterExternalTransport()");
1533
kwiberg55b97fe2016-01-28 05:22:45 -08001534 rtc::CritScope cs(&_callbackCritSect);
kwiberg55b97fe2016-01-28 05:22:45 -08001535 if (_externalTransport) {
1536 _engineStatisticsPtr->SetLastError(
1537 VE_INVALID_OPERATION, kTraceError,
1538 "RegisterExternalTransport() external transport already enabled");
1539 return -1;
1540 }
1541 _externalTransport = true;
mflodman3d7db262016-04-29 00:57:13 -07001542 _transportPtr = transport;
kwiberg55b97fe2016-01-28 05:22:45 -08001543 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001544}
1545
kwiberg55b97fe2016-01-28 05:22:45 -08001546int32_t Channel::DeRegisterExternalTransport() {
1547 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1548 "Channel::DeRegisterExternalTransport()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001549
kwiberg55b97fe2016-01-28 05:22:45 -08001550 rtc::CritScope cs(&_callbackCritSect);
mflodman3d7db262016-04-29 00:57:13 -07001551 if (_transportPtr) {
1552 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1553 "DeRegisterExternalTransport() all transport is disabled");
1554 } else {
kwiberg55b97fe2016-01-28 05:22:45 -08001555 _engineStatisticsPtr->SetLastError(
1556 VE_INVALID_OPERATION, kTraceWarning,
1557 "DeRegisterExternalTransport() external transport already "
1558 "disabled");
kwiberg55b97fe2016-01-28 05:22:45 -08001559 }
1560 _externalTransport = false;
1561 _transportPtr = NULL;
kwiberg55b97fe2016-01-28 05:22:45 -08001562 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001563}
1564
nisse657bab22017-02-21 06:28:10 -08001565// TODO(nisse): Delete this method together with ReceivedRTPPacket.
1566// It's a temporary hack to support both ReceivedRTPPacket and
1567// OnRtpPacket interfaces without too much code duplication.
1568bool Channel::OnRtpPacketWithHeader(const uint8_t* received_packet,
1569 size_t length,
1570 RTPHeader *header) {
1571 // Store playout timestamp for the received RTP packet
1572 UpdatePlayoutTimestamp(false);
1573
1574 header->payload_type_frequency =
1575 rtp_payload_registry_->GetPayloadTypeFrequency(header->payloadType);
1576 if (header->payload_type_frequency < 0)
1577 return false;
1578 bool in_order = IsPacketInOrder(*header);
1579 rtp_receive_statistics_->IncomingPacket(
1580 *header, length, IsPacketRetransmitted(*header, in_order));
1581 rtp_payload_registry_->SetIncomingPayloadType(*header);
1582
1583 return ReceivePacket(received_packet, length, *header, in_order);
1584}
1585
mflodman3d7db262016-04-29 00:57:13 -07001586int32_t Channel::ReceivedRTPPacket(const uint8_t* received_packet,
kwiberg55b97fe2016-01-28 05:22:45 -08001587 size_t length,
solenberg@webrtc.orgb1f50102014-03-24 10:38:25 +00001588 const PacketTime& packet_time) {
kwiberg55b97fe2016-01-28 05:22:45 -08001589 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001590 "Channel::ReceivedRTPPacket()");
1591
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +00001592 RTPHeader header;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001593 if (!rtp_header_parser_->Parse(received_packet, length, &header)) {
1594 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1595 "Incoming packet: invalid RTP header");
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +00001596 return -1;
1597 }
nisse657bab22017-02-21 06:28:10 -08001598 return OnRtpPacketWithHeader(received_packet, length, &header) ? 0 : -1;
1599}
solenberg@webrtc.orgb1f50102014-03-24 10:38:25 +00001600
nisse657bab22017-02-21 06:28:10 -08001601void Channel::OnRtpPacket(const RtpPacketReceived& packet) {
1602 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
1603 "Channel::ReceivedRTPPacket()");
1604
1605 RTPHeader header;
1606 packet.GetHeader(&header);
1607 OnRtpPacketWithHeader(packet.data(), packet.size(), &header);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001608}
1609
1610bool Channel::ReceivePacket(const uint8_t* packet,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001611 size_t packet_length,
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001612 const RTPHeader& header,
1613 bool in_order) {
minyue@webrtc.org456f0142015-01-23 11:58:42 +00001614 if (rtp_payload_registry_->IsRtx(header)) {
1615 return HandleRtxPacket(packet, packet_length, header);
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001616 }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001617 const uint8_t* payload = packet + header.headerLength;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001618 assert(packet_length >= header.headerLength);
1619 size_t payload_length = packet_length - header.headerLength;
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001620 PayloadUnion payload_specific;
1621 if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001622 &payload_specific)) {
1623 return false;
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001624 }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001625 return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
1626 payload_specific, in_order);
1627}
1628
minyue@webrtc.org456f0142015-01-23 11:58:42 +00001629bool Channel::HandleRtxPacket(const uint8_t* packet,
1630 size_t packet_length,
1631 const RTPHeader& header) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001632 if (!rtp_payload_registry_->IsRtx(header))
1633 return false;
1634
1635 // Remove the RTX header and parse the original RTP header.
1636 if (packet_length < header.headerLength)
1637 return false;
1638 if (packet_length > kVoiceEngineMaxIpPacketSizeBytes)
1639 return false;
1640 if (restored_packet_in_use_) {
1641 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1642 "Multiple RTX headers detected, dropping packet");
1643 return false;
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001644 }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001645 if (!rtp_payload_registry_->RestoreOriginalPacket(
noahric65220a72015-10-14 11:29:49 -07001646 restored_packet_, packet, &packet_length, rtp_receiver_->SSRC(),
1647 header)) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001648 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1649 "Incoming RTX packet: invalid RTP header");
1650 return false;
1651 }
1652 restored_packet_in_use_ = true;
noahric65220a72015-10-14 11:29:49 -07001653 bool ret = OnRecoveredPacket(restored_packet_, packet_length);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001654 restored_packet_in_use_ = false;
1655 return ret;
1656}
1657
1658bool Channel::IsPacketInOrder(const RTPHeader& header) const {
1659 StreamStatistician* statistician =
1660 rtp_receive_statistics_->GetStatistician(header.ssrc);
1661 if (!statistician)
1662 return false;
1663 return statistician->IsPacketInOrder(header.sequenceNumber);
niklase@google.com470e71d2011-07-07 08:21:25 +00001664}
1665
stefan@webrtc.org48df3812013-11-08 15:18:52 +00001666bool Channel::IsPacketRetransmitted(const RTPHeader& header,
1667 bool in_order) const {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001668 // Retransmissions are handled separately if RTX is enabled.
1669 if (rtp_payload_registry_->RtxEnabled())
1670 return false;
1671 StreamStatistician* statistician =
1672 rtp_receive_statistics_->GetStatistician(header.ssrc);
1673 if (!statistician)
1674 return false;
1675 // Check if this is a retransmission.
pkasting@chromium.org16825b12015-01-12 21:51:21 +00001676 int64_t min_rtt = 0;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001677 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
kwiberg55b97fe2016-01-28 05:22:45 -08001678 return !in_order && statistician->IsRetransmitOfOldPacket(header, min_rtt);
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001679}
1680
mflodman3d7db262016-04-29 00:57:13 -07001681int32_t Channel::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
kwiberg55b97fe2016-01-28 05:22:45 -08001682 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001683 "Channel::ReceivedRTCPPacket()");
1684 // Store playout timestamp for the received RTCP packet
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00001685 UpdatePlayoutTimestamp(true);
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001686
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001687 // Deliver RTCP packet to RTP/RTCP module for parsing
mflodman3d7db262016-04-29 00:57:13 -07001688 if (_rtpRtcpModule->IncomingRtcpPacket(data, length) == -1) {
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001689 _engineStatisticsPtr->SetLastError(
1690 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
1691 "Channel::IncomingRTPPacket() RTCP packet is invalid");
1692 }
wu@webrtc.org82c4b852014-05-20 22:55:01 +00001693
Minyue2013aec2015-05-13 14:14:42 +02001694 int64_t rtt = GetRTT(true);
1695 if (rtt == 0) {
1696 // Waiting for valid RTT.
1697 return 0;
1698 }
Erik Språng737336d2016-07-29 12:59:36 +02001699
1700 int64_t nack_window_ms = rtt;
1701 if (nack_window_ms < kMinRetransmissionWindowMs) {
1702 nack_window_ms = kMinRetransmissionWindowMs;
1703 } else if (nack_window_ms > kMaxRetransmissionWindowMs) {
1704 nack_window_ms = kMaxRetransmissionWindowMs;
1705 }
1706 retransmission_rate_limiter_->SetWindowSize(nack_window_ms);
1707
minyue7e304322016-10-12 05:00:55 -07001708 // Invoke audio encoders OnReceivedRtt().
1709 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1710 if (*encoder)
1711 (*encoder)->OnReceivedRtt(rtt);
1712 });
1713
Minyue2013aec2015-05-13 14:14:42 +02001714 uint32_t ntp_secs = 0;
1715 uint32_t ntp_frac = 0;
1716 uint32_t rtp_timestamp = 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001717 if (0 !=
1718 _rtpRtcpModule->RemoteNTP(&ntp_secs, &ntp_frac, NULL, NULL,
1719 &rtp_timestamp)) {
Minyue2013aec2015-05-13 14:14:42 +02001720 // Waiting for RTCP.
1721 return 0;
1722 }
1723
stefan@webrtc.org8e24d872014-09-02 18:58:24 +00001724 {
tommi31fc21f2016-01-21 10:37:37 -08001725 rtc::CritScope lock(&ts_stats_lock_);
minyue@webrtc.org2c0cdbc2014-10-09 10:52:43 +00001726 ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp);
stefan@webrtc.org8e24d872014-09-02 18:58:24 +00001727 }
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001728 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001729}
1730
niklase@google.com470e71d2011-07-07 08:21:25 +00001731int Channel::StartPlayingFileLocally(const char* fileName,
pbos@webrtc.org92135212013-05-14 08:31:39 +00001732 bool loop,
1733 FileFormats format,
1734 int startPosition,
1735 float volumeScaling,
1736 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08001737 const CodecInst* codecInst) {
1738 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1739 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
1740 " format=%d, volumeScaling=%5.3f, startPosition=%d, "
1741 "stopPosition=%d)",
1742 fileName, loop, format, volumeScaling, startPosition,
1743 stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00001744
kwiberg55b97fe2016-01-28 05:22:45 -08001745 if (channel_state_.Get().output_file_playing) {
1746 _engineStatisticsPtr->SetLastError(
1747 VE_ALREADY_PLAYING, kTraceError,
1748 "StartPlayingFileLocally() is already playing");
1749 return -1;
1750 }
1751
1752 {
1753 rtc::CritScope cs(&_fileCritSect);
1754
kwiberg5a25d952016-08-17 07:31:12 -07001755 if (output_file_player_) {
1756 output_file_player_->RegisterModuleFileCallback(NULL);
1757 output_file_player_.reset();
niklase@google.com470e71d2011-07-07 08:21:25 +00001758 }
1759
kwiberg5b356f42016-09-08 04:32:33 -07001760 output_file_player_ = FilePlayer::CreateFilePlayer(
kwiberg55b97fe2016-01-28 05:22:45 -08001761 _outputFilePlayerId, (const FileFormats)format);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00001762
kwiberg5a25d952016-08-17 07:31:12 -07001763 if (!output_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08001764 _engineStatisticsPtr->SetLastError(
1765 VE_INVALID_ARGUMENT, kTraceError,
1766 "StartPlayingFileLocally() filePlayer format is not correct");
1767 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001768 }
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001769
kwiberg55b97fe2016-01-28 05:22:45 -08001770 const uint32_t notificationTime(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00001771
kwiberg5a25d952016-08-17 07:31:12 -07001772 if (output_file_player_->StartPlayingFile(
kwiberg55b97fe2016-01-28 05:22:45 -08001773 fileName, loop, startPosition, volumeScaling, notificationTime,
1774 stopPosition, (const CodecInst*)codecInst) != 0) {
1775 _engineStatisticsPtr->SetLastError(
1776 VE_BAD_FILE, kTraceError,
1777 "StartPlayingFile() failed to start file playout");
kwiberg5a25d952016-08-17 07:31:12 -07001778 output_file_player_->StopPlayingFile();
1779 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001780 return -1;
1781 }
kwiberg5a25d952016-08-17 07:31:12 -07001782 output_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08001783 channel_state_.SetOutputFilePlaying(true);
1784 }
1785
1786 if (RegisterFilePlayingToMixer() != 0)
1787 return -1;
1788
1789 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001790}
1791
1792int Channel::StartPlayingFileLocally(InStream* stream,
pbos@webrtc.org92135212013-05-14 08:31:39 +00001793 FileFormats format,
1794 int startPosition,
1795 float volumeScaling,
1796 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08001797 const CodecInst* codecInst) {
1798 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1799 "Channel::StartPlayingFileLocally(format=%d,"
1800 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
1801 format, volumeScaling, startPosition, stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00001802
kwiberg55b97fe2016-01-28 05:22:45 -08001803 if (stream == NULL) {
1804 _engineStatisticsPtr->SetLastError(
1805 VE_BAD_FILE, kTraceError,
1806 "StartPlayingFileLocally() NULL as input stream");
1807 return -1;
1808 }
1809
1810 if (channel_state_.Get().output_file_playing) {
1811 _engineStatisticsPtr->SetLastError(
1812 VE_ALREADY_PLAYING, kTraceError,
1813 "StartPlayingFileLocally() is already playing");
1814 return -1;
1815 }
1816
1817 {
1818 rtc::CritScope cs(&_fileCritSect);
1819
1820 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07001821 if (output_file_player_) {
1822 output_file_player_->RegisterModuleFileCallback(NULL);
1823 output_file_player_.reset();
niklase@google.com470e71d2011-07-07 08:21:25 +00001824 }
1825
kwiberg55b97fe2016-01-28 05:22:45 -08001826 // Create the instance
kwiberg5b356f42016-09-08 04:32:33 -07001827 output_file_player_ = FilePlayer::CreateFilePlayer(
kwiberg55b97fe2016-01-28 05:22:45 -08001828 _outputFilePlayerId, (const FileFormats)format);
niklase@google.com470e71d2011-07-07 08:21:25 +00001829
kwiberg5a25d952016-08-17 07:31:12 -07001830 if (!output_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08001831 _engineStatisticsPtr->SetLastError(
1832 VE_INVALID_ARGUMENT, kTraceError,
1833 "StartPlayingFileLocally() filePlayer format isnot correct");
1834 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001835 }
1836
kwiberg55b97fe2016-01-28 05:22:45 -08001837 const uint32_t notificationTime(0);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00001838
kwiberg4ec01d92016-08-22 08:43:54 -07001839 if (output_file_player_->StartPlayingFile(stream, startPosition,
kwiberg5a25d952016-08-17 07:31:12 -07001840 volumeScaling, notificationTime,
1841 stopPosition, codecInst) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001842 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
1843 "StartPlayingFile() failed to "
1844 "start file playout");
kwiberg5a25d952016-08-17 07:31:12 -07001845 output_file_player_->StopPlayingFile();
1846 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001847 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001848 }
kwiberg5a25d952016-08-17 07:31:12 -07001849 output_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08001850 channel_state_.SetOutputFilePlaying(true);
1851 }
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001852
kwiberg55b97fe2016-01-28 05:22:45 -08001853 if (RegisterFilePlayingToMixer() != 0)
1854 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001855
kwiberg55b97fe2016-01-28 05:22:45 -08001856 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001857}
1858
kwiberg55b97fe2016-01-28 05:22:45 -08001859int Channel::StopPlayingFileLocally() {
1860 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1861 "Channel::StopPlayingFileLocally()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001862
kwiberg55b97fe2016-01-28 05:22:45 -08001863 if (!channel_state_.Get().output_file_playing) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001864 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001865 }
1866
1867 {
1868 rtc::CritScope cs(&_fileCritSect);
1869
kwiberg5a25d952016-08-17 07:31:12 -07001870 if (output_file_player_->StopPlayingFile() != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001871 _engineStatisticsPtr->SetLastError(
1872 VE_STOP_RECORDING_FAILED, kTraceError,
1873 "StopPlayingFile() could not stop playing");
1874 return -1;
1875 }
kwiberg5a25d952016-08-17 07:31:12 -07001876 output_file_player_->RegisterModuleFileCallback(NULL);
1877 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001878 channel_state_.SetOutputFilePlaying(false);
1879 }
1880 // _fileCritSect cannot be taken while calling
1881 // SetAnonymousMixibilityStatus. Refer to comments in
1882 // StartPlayingFileLocally(const char* ...) for more details.
1883 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0) {
1884 _engineStatisticsPtr->SetLastError(
1885 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1886 "StopPlayingFile() failed to stop participant from playing as"
1887 "file in the mixer");
1888 return -1;
1889 }
1890
1891 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001892}
1893
kwiberg55b97fe2016-01-28 05:22:45 -08001894int Channel::IsPlayingFileLocally() const {
1895 return channel_state_.Get().output_file_playing;
niklase@google.com470e71d2011-07-07 08:21:25 +00001896}
1897
kwiberg55b97fe2016-01-28 05:22:45 -08001898int Channel::RegisterFilePlayingToMixer() {
1899 // Return success for not registering for file playing to mixer if:
1900 // 1. playing file before playout is started on that channel.
1901 // 2. starting playout without file playing on that channel.
1902 if (!channel_state_.Get().playing ||
1903 !channel_state_.Get().output_file_playing) {
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001904 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001905 }
1906
1907 // |_fileCritSect| cannot be taken while calling
1908 // SetAnonymousMixabilityStatus() since as soon as the participant is added
1909 // frames can be pulled by the mixer. Since the frames are generated from
1910 // the file, _fileCritSect will be taken. This would result in a deadlock.
1911 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0) {
1912 channel_state_.SetOutputFilePlaying(false);
1913 rtc::CritScope cs(&_fileCritSect);
1914 _engineStatisticsPtr->SetLastError(
1915 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1916 "StartPlayingFile() failed to add participant as file to mixer");
kwiberg5a25d952016-08-17 07:31:12 -07001917 output_file_player_->StopPlayingFile();
1918 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001919 return -1;
1920 }
1921
1922 return 0;
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001923}
1924
niklase@google.com470e71d2011-07-07 08:21:25 +00001925int Channel::StartPlayingFileAsMicrophone(const char* fileName,
pbos@webrtc.org92135212013-05-14 08:31:39 +00001926 bool loop,
1927 FileFormats format,
1928 int startPosition,
1929 float volumeScaling,
1930 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08001931 const CodecInst* codecInst) {
1932 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1933 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
1934 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
1935 "stopPosition=%d)",
1936 fileName, loop, format, volumeScaling, startPosition,
1937 stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00001938
kwiberg55b97fe2016-01-28 05:22:45 -08001939 rtc::CritScope cs(&_fileCritSect);
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +00001940
kwiberg55b97fe2016-01-28 05:22:45 -08001941 if (channel_state_.Get().input_file_playing) {
1942 _engineStatisticsPtr->SetLastError(
1943 VE_ALREADY_PLAYING, kTraceWarning,
1944 "StartPlayingFileAsMicrophone() filePlayer is playing");
niklase@google.com470e71d2011-07-07 08:21:25 +00001945 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001946 }
1947
1948 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07001949 if (input_file_player_) {
1950 input_file_player_->RegisterModuleFileCallback(NULL);
1951 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001952 }
1953
1954 // Create the instance
kwiberg5b356f42016-09-08 04:32:33 -07001955 input_file_player_ = FilePlayer::CreateFilePlayer(_inputFilePlayerId,
kwiberg5a25d952016-08-17 07:31:12 -07001956 (const FileFormats)format);
kwiberg55b97fe2016-01-28 05:22:45 -08001957
kwiberg5a25d952016-08-17 07:31:12 -07001958 if (!input_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08001959 _engineStatisticsPtr->SetLastError(
1960 VE_INVALID_ARGUMENT, kTraceError,
1961 "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
1962 return -1;
1963 }
1964
1965 const uint32_t notificationTime(0);
1966
kwiberg5a25d952016-08-17 07:31:12 -07001967 if (input_file_player_->StartPlayingFile(
kwiberg55b97fe2016-01-28 05:22:45 -08001968 fileName, loop, startPosition, volumeScaling, notificationTime,
1969 stopPosition, (const CodecInst*)codecInst) != 0) {
1970 _engineStatisticsPtr->SetLastError(
1971 VE_BAD_FILE, kTraceError,
1972 "StartPlayingFile() failed to start file playout");
kwiberg5a25d952016-08-17 07:31:12 -07001973 input_file_player_->StopPlayingFile();
1974 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001975 return -1;
1976 }
kwiberg5a25d952016-08-17 07:31:12 -07001977 input_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08001978 channel_state_.SetInputFilePlaying(true);
1979
1980 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001981}
1982
1983int Channel::StartPlayingFileAsMicrophone(InStream* stream,
pbos@webrtc.org92135212013-05-14 08:31:39 +00001984 FileFormats format,
1985 int startPosition,
1986 float volumeScaling,
1987 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08001988 const CodecInst* codecInst) {
1989 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1990 "Channel::StartPlayingFileAsMicrophone(format=%d, "
1991 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
1992 format, volumeScaling, startPosition, stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00001993
kwiberg55b97fe2016-01-28 05:22:45 -08001994 if (stream == NULL) {
1995 _engineStatisticsPtr->SetLastError(
1996 VE_BAD_FILE, kTraceError,
1997 "StartPlayingFileAsMicrophone NULL as input stream");
1998 return -1;
1999 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002000
kwiberg55b97fe2016-01-28 05:22:45 -08002001 rtc::CritScope cs(&_fileCritSect);
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +00002002
kwiberg55b97fe2016-01-28 05:22:45 -08002003 if (channel_state_.Get().input_file_playing) {
2004 _engineStatisticsPtr->SetLastError(
2005 VE_ALREADY_PLAYING, kTraceWarning,
2006 "StartPlayingFileAsMicrophone() is playing");
niklase@google.com470e71d2011-07-07 08:21:25 +00002007 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08002008 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002009
kwiberg55b97fe2016-01-28 05:22:45 -08002010 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07002011 if (input_file_player_) {
2012 input_file_player_->RegisterModuleFileCallback(NULL);
2013 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002014 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002015
kwiberg55b97fe2016-01-28 05:22:45 -08002016 // Create the instance
kwiberg5b356f42016-09-08 04:32:33 -07002017 input_file_player_ = FilePlayer::CreateFilePlayer(_inputFilePlayerId,
kwiberg5a25d952016-08-17 07:31:12 -07002018 (const FileFormats)format);
kwiberg55b97fe2016-01-28 05:22:45 -08002019
kwiberg5a25d952016-08-17 07:31:12 -07002020 if (!input_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002021 _engineStatisticsPtr->SetLastError(
2022 VE_INVALID_ARGUMENT, kTraceError,
2023 "StartPlayingInputFile() filePlayer format isnot correct");
2024 return -1;
2025 }
2026
2027 const uint32_t notificationTime(0);
2028
kwiberg4ec01d92016-08-22 08:43:54 -07002029 if (input_file_player_->StartPlayingFile(stream, startPosition, volumeScaling,
2030 notificationTime, stopPosition,
2031 codecInst) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002032 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2033 "StartPlayingFile() failed to start "
2034 "file playout");
kwiberg5a25d952016-08-17 07:31:12 -07002035 input_file_player_->StopPlayingFile();
2036 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002037 return -1;
2038 }
2039
kwiberg5a25d952016-08-17 07:31:12 -07002040 input_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08002041 channel_state_.SetInputFilePlaying(true);
2042
2043 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002044}
2045
kwiberg55b97fe2016-01-28 05:22:45 -08002046int Channel::StopPlayingFileAsMicrophone() {
2047 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2048 "Channel::StopPlayingFileAsMicrophone()");
2049
2050 rtc::CritScope cs(&_fileCritSect);
2051
2052 if (!channel_state_.Get().input_file_playing) {
2053 return 0;
2054 }
2055
kwiberg5a25d952016-08-17 07:31:12 -07002056 if (input_file_player_->StopPlayingFile() != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002057 _engineStatisticsPtr->SetLastError(
2058 VE_STOP_RECORDING_FAILED, kTraceError,
2059 "StopPlayingFile() could not stop playing");
2060 return -1;
2061 }
kwiberg5a25d952016-08-17 07:31:12 -07002062 input_file_player_->RegisterModuleFileCallback(NULL);
2063 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002064 channel_state_.SetInputFilePlaying(false);
2065
2066 return 0;
2067}
2068
2069int Channel::IsPlayingFileAsMicrophone() const {
2070 return channel_state_.Get().input_file_playing;
niklase@google.com470e71d2011-07-07 08:21:25 +00002071}
2072
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002073int Channel::StartRecordingPlayout(const char* fileName,
kwiberg55b97fe2016-01-28 05:22:45 -08002074 const CodecInst* codecInst) {
2075 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2076 "Channel::StartRecordingPlayout(fileName=%s)", fileName);
niklase@google.com470e71d2011-07-07 08:21:25 +00002077
kwiberg55b97fe2016-01-28 05:22:45 -08002078 if (_outputFileRecording) {
2079 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
2080 "StartRecordingPlayout() is already recording");
niklase@google.com470e71d2011-07-07 08:21:25 +00002081 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08002082 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002083
kwiberg55b97fe2016-01-28 05:22:45 -08002084 FileFormats format;
2085 const uint32_t notificationTime(0); // Not supported in VoE
2086 CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
niklase@google.com470e71d2011-07-07 08:21:25 +00002087
kwiberg55b97fe2016-01-28 05:22:45 -08002088 if ((codecInst != NULL) &&
2089 ((codecInst->channels < 1) || (codecInst->channels > 2))) {
2090 _engineStatisticsPtr->SetLastError(
2091 VE_BAD_ARGUMENT, kTraceError,
2092 "StartRecordingPlayout() invalid compression");
2093 return (-1);
2094 }
2095 if (codecInst == NULL) {
2096 format = kFileFormatPcm16kHzFile;
2097 codecInst = &dummyCodec;
2098 } else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
2099 (STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
2100 (STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
2101 format = kFileFormatWavFile;
2102 } else {
2103 format = kFileFormatCompressedFile;
2104 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002105
kwiberg55b97fe2016-01-28 05:22:45 -08002106 rtc::CritScope cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002107
kwiberg55b97fe2016-01-28 05:22:45 -08002108 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07002109 if (output_file_recorder_) {
2110 output_file_recorder_->RegisterModuleFileCallback(NULL);
2111 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002112 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002113
kwiberg5a25d952016-08-17 07:31:12 -07002114 output_file_recorder_ = FileRecorder::CreateFileRecorder(
kwiberg55b97fe2016-01-28 05:22:45 -08002115 _outputFileRecorderId, (const FileFormats)format);
kwiberg5a25d952016-08-17 07:31:12 -07002116 if (!output_file_recorder_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002117 _engineStatisticsPtr->SetLastError(
2118 VE_INVALID_ARGUMENT, kTraceError,
2119 "StartRecordingPlayout() fileRecorder format isnot correct");
2120 return -1;
2121 }
2122
kwiberg5a25d952016-08-17 07:31:12 -07002123 if (output_file_recorder_->StartRecordingAudioFile(
kwiberg55b97fe2016-01-28 05:22:45 -08002124 fileName, (const CodecInst&)*codecInst, notificationTime) != 0) {
2125 _engineStatisticsPtr->SetLastError(
2126 VE_BAD_FILE, kTraceError,
2127 "StartRecordingAudioFile() failed to start file recording");
kwiberg5a25d952016-08-17 07:31:12 -07002128 output_file_recorder_->StopRecording();
2129 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002130 return -1;
2131 }
kwiberg5a25d952016-08-17 07:31:12 -07002132 output_file_recorder_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08002133 _outputFileRecording = true;
2134
2135 return 0;
2136}
2137
2138int Channel::StartRecordingPlayout(OutStream* stream,
2139 const CodecInst* codecInst) {
2140 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2141 "Channel::StartRecordingPlayout()");
2142
2143 if (_outputFileRecording) {
2144 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
2145 "StartRecordingPlayout() is already recording");
niklase@google.com470e71d2011-07-07 08:21:25 +00002146 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08002147 }
2148
2149 FileFormats format;
2150 const uint32_t notificationTime(0); // Not supported in VoE
2151 CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
2152
2153 if (codecInst != NULL && codecInst->channels != 1) {
2154 _engineStatisticsPtr->SetLastError(
2155 VE_BAD_ARGUMENT, kTraceError,
2156 "StartRecordingPlayout() invalid compression");
2157 return (-1);
2158 }
2159 if (codecInst == NULL) {
2160 format = kFileFormatPcm16kHzFile;
2161 codecInst = &dummyCodec;
2162 } else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
2163 (STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
2164 (STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
2165 format = kFileFormatWavFile;
2166 } else {
2167 format = kFileFormatCompressedFile;
2168 }
2169
2170 rtc::CritScope cs(&_fileCritSect);
2171
2172 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07002173 if (output_file_recorder_) {
2174 output_file_recorder_->RegisterModuleFileCallback(NULL);
2175 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002176 }
2177
kwiberg5a25d952016-08-17 07:31:12 -07002178 output_file_recorder_ = FileRecorder::CreateFileRecorder(
kwiberg55b97fe2016-01-28 05:22:45 -08002179 _outputFileRecorderId, (const FileFormats)format);
kwiberg5a25d952016-08-17 07:31:12 -07002180 if (!output_file_recorder_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002181 _engineStatisticsPtr->SetLastError(
2182 VE_INVALID_ARGUMENT, kTraceError,
2183 "StartRecordingPlayout() fileRecorder format isnot correct");
2184 return -1;
2185 }
2186
kwiberg4ec01d92016-08-22 08:43:54 -07002187 if (output_file_recorder_->StartRecordingAudioFile(stream, *codecInst,
kwiberg5a25d952016-08-17 07:31:12 -07002188 notificationTime) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002189 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2190 "StartRecordingPlayout() failed to "
2191 "start file recording");
kwiberg5a25d952016-08-17 07:31:12 -07002192 output_file_recorder_->StopRecording();
2193 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002194 return -1;
2195 }
2196
kwiberg5a25d952016-08-17 07:31:12 -07002197 output_file_recorder_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08002198 _outputFileRecording = true;
2199
2200 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002201}
2202
kwiberg55b97fe2016-01-28 05:22:45 -08002203int Channel::StopRecordingPlayout() {
2204 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
2205 "Channel::StopRecordingPlayout()");
2206
2207 if (!_outputFileRecording) {
2208 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1),
2209 "StopRecordingPlayout() isnot recording");
2210 return -1;
2211 }
2212
2213 rtc::CritScope cs(&_fileCritSect);
2214
kwiberg5a25d952016-08-17 07:31:12 -07002215 if (output_file_recorder_->StopRecording() != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002216 _engineStatisticsPtr->SetLastError(
2217 VE_STOP_RECORDING_FAILED, kTraceError,
2218 "StopRecording() could not stop recording");
2219 return (-1);
2220 }
kwiberg5a25d952016-08-17 07:31:12 -07002221 output_file_recorder_->RegisterModuleFileCallback(NULL);
2222 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002223 _outputFileRecording = false;
2224
2225 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002226}
2227
kwiberg55b97fe2016-01-28 05:22:45 -08002228void Channel::SetMixWithMicStatus(bool mix) {
2229 rtc::CritScope cs(&_fileCritSect);
2230 _mixFileWithMicrophone = mix;
niklase@google.com470e71d2011-07-07 08:21:25 +00002231}
2232
kwiberg55b97fe2016-01-28 05:22:45 -08002233int Channel::GetSpeechOutputLevel(uint32_t& level) const {
2234 int8_t currentLevel = _outputAudioLevel.Level();
2235 level = static_cast<int32_t>(currentLevel);
2236 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002237}
2238
kwiberg55b97fe2016-01-28 05:22:45 -08002239int Channel::GetSpeechOutputLevelFullRange(uint32_t& level) const {
2240 int16_t currentLevel = _outputAudioLevel.LevelFullRange();
2241 level = static_cast<int32_t>(currentLevel);
2242 return 0;
2243}
2244
solenberg1c2af8e2016-03-24 10:36:00 -07002245int Channel::SetInputMute(bool enable) {
kwiberg55b97fe2016-01-28 05:22:45 -08002246 rtc::CritScope cs(&volume_settings_critsect_);
2247 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002248 "Channel::SetMute(enable=%d)", enable);
solenberg1c2af8e2016-03-24 10:36:00 -07002249 input_mute_ = enable;
kwiberg55b97fe2016-01-28 05:22:45 -08002250 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002251}
2252
solenberg1c2af8e2016-03-24 10:36:00 -07002253bool Channel::InputMute() const {
kwiberg55b97fe2016-01-28 05:22:45 -08002254 rtc::CritScope cs(&volume_settings_critsect_);
solenberg1c2af8e2016-03-24 10:36:00 -07002255 return input_mute_;
niklase@google.com470e71d2011-07-07 08:21:25 +00002256}
2257
kwiberg55b97fe2016-01-28 05:22:45 -08002258int Channel::SetOutputVolumePan(float left, float right) {
2259 rtc::CritScope cs(&volume_settings_critsect_);
2260 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002261 "Channel::SetOutputVolumePan()");
kwiberg55b97fe2016-01-28 05:22:45 -08002262 _panLeft = left;
2263 _panRight = right;
2264 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002265}
2266
kwiberg55b97fe2016-01-28 05:22:45 -08002267int Channel::GetOutputVolumePan(float& left, float& right) const {
2268 rtc::CritScope cs(&volume_settings_critsect_);
2269 left = _panLeft;
2270 right = _panRight;
2271 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002272}
2273
kwiberg55b97fe2016-01-28 05:22:45 -08002274int Channel::SetChannelOutputVolumeScaling(float scaling) {
2275 rtc::CritScope cs(&volume_settings_critsect_);
2276 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002277 "Channel::SetChannelOutputVolumeScaling()");
kwiberg55b97fe2016-01-28 05:22:45 -08002278 _outputGain = scaling;
2279 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002280}
2281
kwiberg55b97fe2016-01-28 05:22:45 -08002282int Channel::GetChannelOutputVolumeScaling(float& scaling) const {
2283 rtc::CritScope cs(&volume_settings_critsect_);
2284 scaling = _outputGain;
2285 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002286}
2287
solenberg8842c3e2016-03-11 03:06:41 -08002288int Channel::SendTelephoneEventOutband(int event, int duration_ms) {
kwiberg55b97fe2016-01-28 05:22:45 -08002289 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
solenberg8842c3e2016-03-11 03:06:41 -08002290 "Channel::SendTelephoneEventOutband(...)");
2291 RTC_DCHECK_LE(0, event);
2292 RTC_DCHECK_GE(255, event);
2293 RTC_DCHECK_LE(0, duration_ms);
2294 RTC_DCHECK_GE(65535, duration_ms);
kwiberg55b97fe2016-01-28 05:22:45 -08002295 if (!Sending()) {
2296 return -1;
2297 }
solenberg8842c3e2016-03-11 03:06:41 -08002298 if (_rtpRtcpModule->SendTelephoneEventOutband(
2299 event, duration_ms, kTelephoneEventAttenuationdB) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002300 _engineStatisticsPtr->SetLastError(
2301 VE_SEND_DTMF_FAILED, kTraceWarning,
2302 "SendTelephoneEventOutband() failed to send event");
2303 return -1;
2304 }
2305 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002306}
2307
solenbergffbbcac2016-11-17 05:25:37 -08002308int Channel::SetSendTelephoneEventPayloadType(int payload_type,
2309 int payload_frequency) {
kwiberg55b97fe2016-01-28 05:22:45 -08002310 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002311 "Channel::SetSendTelephoneEventPayloadType()");
solenberg31642aa2016-03-14 08:00:37 -07002312 RTC_DCHECK_LE(0, payload_type);
2313 RTC_DCHECK_GE(127, payload_type);
2314 CodecInst codec = {0};
solenberg31642aa2016-03-14 08:00:37 -07002315 codec.pltype = payload_type;
solenbergffbbcac2016-11-17 05:25:37 -08002316 codec.plfreq = payload_frequency;
kwiberg55b97fe2016-01-28 05:22:45 -08002317 memcpy(codec.plname, "telephone-event", 16);
2318 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
2319 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
2320 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
2321 _engineStatisticsPtr->SetLastError(
2322 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2323 "SetSendTelephoneEventPayloadType() failed to register send"
2324 "payload type");
2325 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002326 }
kwiberg55b97fe2016-01-28 05:22:45 -08002327 }
kwiberg55b97fe2016-01-28 05:22:45 -08002328 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002329}
2330
kwiberg55b97fe2016-01-28 05:22:45 -08002331int Channel::VoiceActivityIndicator(int& activity) {
2332 activity = _sendFrameType;
2333 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002334}
2335
kwiberg55b97fe2016-01-28 05:22:45 -08002336int Channel::SetLocalSSRC(unsigned int ssrc) {
2337 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2338 "Channel::SetLocalSSRC()");
2339 if (channel_state_.Get().sending) {
2340 _engineStatisticsPtr->SetLastError(VE_ALREADY_SENDING, kTraceError,
2341 "SetLocalSSRC() already sending");
2342 return -1;
2343 }
2344 _rtpRtcpModule->SetSSRC(ssrc);
2345 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002346}
2347
kwiberg55b97fe2016-01-28 05:22:45 -08002348int Channel::GetLocalSSRC(unsigned int& ssrc) {
2349 ssrc = _rtpRtcpModule->SSRC();
2350 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002351}
2352
kwiberg55b97fe2016-01-28 05:22:45 -08002353int Channel::GetRemoteSSRC(unsigned int& ssrc) {
2354 ssrc = rtp_receiver_->SSRC();
2355 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002356}
2357
wu@webrtc.orgebdb0e32014-03-06 23:49:08 +00002358int Channel::SetSendAudioLevelIndicationStatus(bool enable, unsigned char id) {
andrew@webrtc.orgf3930e92013-09-18 22:37:32 +00002359 _includeAudioLevelIndication = enable;
wu@webrtc.orgebdb0e32014-03-06 23:49:08 +00002360 return SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id);
niklase@google.com470e71d2011-07-07 08:21:25 +00002361}
andrew@webrtc.orgf3930e92013-09-18 22:37:32 +00002362
wu@webrtc.org93fd25c2014-04-24 20:33:08 +00002363int Channel::SetReceiveAudioLevelIndicationStatus(bool enable,
2364 unsigned char id) {
kwiberg55b97fe2016-01-28 05:22:45 -08002365 rtp_header_parser_->DeregisterRtpHeaderExtension(kRtpExtensionAudioLevel);
2366 if (enable &&
2367 !rtp_header_parser_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
2368 id)) {
wu@webrtc.org93fd25c2014-04-24 20:33:08 +00002369 return -1;
2370 }
2371 return 0;
2372}
2373
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002374void Channel::EnableSendTransportSequenceNumber(int id) {
2375 int ret =
2376 SetSendRtpHeaderExtension(true, kRtpExtensionTransportSequenceNumber, id);
2377 RTC_DCHECK_EQ(0, ret);
2378}
2379
stefan3313ec92016-01-21 06:32:43 -08002380void Channel::EnableReceiveTransportSequenceNumber(int id) {
2381 rtp_header_parser_->DeregisterRtpHeaderExtension(
2382 kRtpExtensionTransportSequenceNumber);
2383 bool ret = rtp_header_parser_->RegisterRtpHeaderExtension(
2384 kRtpExtensionTransportSequenceNumber, id);
2385 RTC_DCHECK(ret);
2386}
2387
stefanbba9dec2016-02-01 04:39:55 -08002388void Channel::RegisterSenderCongestionControlObjects(
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002389 RtpPacketSender* rtp_packet_sender,
2390 TransportFeedbackObserver* transport_feedback_observer,
stefan7de8d642017-02-07 07:14:08 -08002391 PacketRouter* packet_router,
2392 RtcpBandwidthObserver* bandwidth_observer) {
stefanbba9dec2016-02-01 04:39:55 -08002393 RTC_DCHECK(rtp_packet_sender);
2394 RTC_DCHECK(transport_feedback_observer);
2395 RTC_DCHECK(packet_router && !packet_router_);
stefan7de8d642017-02-07 07:14:08 -08002396 rtcp_observer_->SetBandwidthObserver(bandwidth_observer);
stefanbba9dec2016-02-01 04:39:55 -08002397 feedback_observer_proxy_->SetTransportFeedbackObserver(
2398 transport_feedback_observer);
2399 seq_num_allocator_proxy_->SetSequenceNumberAllocator(packet_router);
2400 rtp_packet_sender_proxy_->SetPacketSender(rtp_packet_sender);
2401 _rtpRtcpModule->SetStorePacketsStatus(true, 600);
Peter Boström3dd5d1d2016-02-25 16:56:48 +01002402 packet_router->AddRtpModule(_rtpRtcpModule.get());
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002403 packet_router_ = packet_router;
2404}
2405
stefanbba9dec2016-02-01 04:39:55 -08002406void Channel::RegisterReceiverCongestionControlObjects(
2407 PacketRouter* packet_router) {
2408 RTC_DCHECK(packet_router && !packet_router_);
Peter Boström3dd5d1d2016-02-25 16:56:48 +01002409 packet_router->AddRtpModule(_rtpRtcpModule.get());
stefanbba9dec2016-02-01 04:39:55 -08002410 packet_router_ = packet_router;
2411}
2412
2413void Channel::ResetCongestionControlObjects() {
2414 RTC_DCHECK(packet_router_);
2415 _rtpRtcpModule->SetStorePacketsStatus(false, 600);
stefan7de8d642017-02-07 07:14:08 -08002416 rtcp_observer_->SetBandwidthObserver(nullptr);
stefanbba9dec2016-02-01 04:39:55 -08002417 feedback_observer_proxy_->SetTransportFeedbackObserver(nullptr);
2418 seq_num_allocator_proxy_->SetSequenceNumberAllocator(nullptr);
Peter Boström3dd5d1d2016-02-25 16:56:48 +01002419 packet_router_->RemoveRtpModule(_rtpRtcpModule.get());
stefanbba9dec2016-02-01 04:39:55 -08002420 packet_router_ = nullptr;
2421 rtp_packet_sender_proxy_->SetPacketSender(nullptr);
2422}
2423
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00002424void Channel::SetRTCPStatus(bool enable) {
2425 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2426 "Channel::SetRTCPStatus()");
pbosda903ea2015-10-02 02:36:56 -07002427 _rtpRtcpModule->SetRTCPStatus(enable ? RtcpMode::kCompound : RtcpMode::kOff);
niklase@google.com470e71d2011-07-07 08:21:25 +00002428}
2429
kwiberg55b97fe2016-01-28 05:22:45 -08002430int Channel::GetRTCPStatus(bool& enabled) {
pbosda903ea2015-10-02 02:36:56 -07002431 RtcpMode method = _rtpRtcpModule->RTCP();
2432 enabled = (method != RtcpMode::kOff);
kwiberg55b97fe2016-01-28 05:22:45 -08002433 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002434}
2435
kwiberg55b97fe2016-01-28 05:22:45 -08002436int Channel::SetRTCP_CNAME(const char cName[256]) {
2437 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2438 "Channel::SetRTCP_CNAME()");
2439 if (_rtpRtcpModule->SetCNAME(cName) != 0) {
2440 _engineStatisticsPtr->SetLastError(
2441 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2442 "SetRTCP_CNAME() failed to set RTCP CNAME");
2443 return -1;
2444 }
2445 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002446}
2447
kwiberg55b97fe2016-01-28 05:22:45 -08002448int Channel::GetRemoteRTCP_CNAME(char cName[256]) {
2449 if (cName == NULL) {
2450 _engineStatisticsPtr->SetLastError(
2451 VE_INVALID_ARGUMENT, kTraceError,
2452 "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
2453 return -1;
2454 }
2455 char cname[RTCP_CNAME_SIZE];
2456 const uint32_t remoteSSRC = rtp_receiver_->SSRC();
2457 if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0) {
2458 _engineStatisticsPtr->SetLastError(
2459 VE_CANNOT_RETRIEVE_CNAME, kTraceError,
2460 "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
2461 return -1;
2462 }
2463 strcpy(cName, cname);
2464 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002465}
2466
kwiberg55b97fe2016-01-28 05:22:45 -08002467int Channel::SendApplicationDefinedRTCPPacket(
2468 unsigned char subType,
2469 unsigned int name,
2470 const char* data,
2471 unsigned short dataLengthInBytes) {
2472 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2473 "Channel::SendApplicationDefinedRTCPPacket()");
2474 if (!channel_state_.Get().sending) {
2475 _engineStatisticsPtr->SetLastError(
2476 VE_NOT_SENDING, kTraceError,
2477 "SendApplicationDefinedRTCPPacket() not sending");
2478 return -1;
2479 }
2480 if (NULL == data) {
2481 _engineStatisticsPtr->SetLastError(
2482 VE_INVALID_ARGUMENT, kTraceError,
2483 "SendApplicationDefinedRTCPPacket() invalid data value");
2484 return -1;
2485 }
2486 if (dataLengthInBytes % 4 != 0) {
2487 _engineStatisticsPtr->SetLastError(
2488 VE_INVALID_ARGUMENT, kTraceError,
2489 "SendApplicationDefinedRTCPPacket() invalid length value");
2490 return -1;
2491 }
2492 RtcpMode status = _rtpRtcpModule->RTCP();
2493 if (status == RtcpMode::kOff) {
2494 _engineStatisticsPtr->SetLastError(
2495 VE_RTCP_ERROR, kTraceError,
2496 "SendApplicationDefinedRTCPPacket() RTCP is disabled");
2497 return -1;
2498 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002499
kwiberg55b97fe2016-01-28 05:22:45 -08002500 // Create and schedule the RTCP APP packet for transmission
2501 if (_rtpRtcpModule->SetRTCPApplicationSpecificData(
2502 subType, name, (const unsigned char*)data, dataLengthInBytes) != 0) {
2503 _engineStatisticsPtr->SetLastError(
2504 VE_SEND_ERROR, kTraceError,
2505 "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
2506 return -1;
2507 }
2508 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002509}
2510
henrika@webrtc.org8a2fc882012-08-22 08:53:55 +00002511int Channel::GetRemoteRTCPReportBlocks(
2512 std::vector<ReportBlock>* report_blocks) {
2513 if (report_blocks == NULL) {
kwiberg55b97fe2016-01-28 05:22:45 -08002514 _engineStatisticsPtr->SetLastError(
2515 VE_INVALID_ARGUMENT, kTraceError,
2516 "GetRemoteRTCPReportBlock()s invalid report_blocks.");
henrika@webrtc.org8a2fc882012-08-22 08:53:55 +00002517 return -1;
2518 }
2519
2520 // Get the report blocks from the latest received RTCP Sender or Receiver
2521 // Report. Each element in the vector contains the sender's SSRC and a
2522 // report block according to RFC 3550.
2523 std::vector<RTCPReportBlock> rtcp_report_blocks;
2524 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) {
henrika@webrtc.org8a2fc882012-08-22 08:53:55 +00002525 return -1;
2526 }
2527
2528 if (rtcp_report_blocks.empty())
2529 return 0;
2530
2531 std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
2532 for (; it != rtcp_report_blocks.end(); ++it) {
2533 ReportBlock report_block;
2534 report_block.sender_SSRC = it->remoteSSRC;
2535 report_block.source_SSRC = it->sourceSSRC;
2536 report_block.fraction_lost = it->fractionLost;
2537 report_block.cumulative_num_packets_lost = it->cumulativeLost;
2538 report_block.extended_highest_sequence_number = it->extendedHighSeqNum;
2539 report_block.interarrival_jitter = it->jitter;
2540 report_block.last_SR_timestamp = it->lastSR;
2541 report_block.delay_since_last_SR = it->delaySinceLastSR;
2542 report_blocks->push_back(report_block);
2543 }
2544 return 0;
2545}
2546
kwiberg55b97fe2016-01-28 05:22:45 -08002547int Channel::GetRTPStatistics(CallStatistics& stats) {
2548 // --- RtcpStatistics
niklase@google.com470e71d2011-07-07 08:21:25 +00002549
kwiberg55b97fe2016-01-28 05:22:45 -08002550 // The jitter statistics is updated for each received RTP packet and is
2551 // based on received packets.
2552 RtcpStatistics statistics;
2553 StreamStatistician* statistician =
2554 rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
Peter Boström59013bc2016-02-12 11:35:08 +01002555 if (statistician) {
2556 statistician->GetStatistics(&statistics,
2557 _rtpRtcpModule->RTCP() == RtcpMode::kOff);
kwiberg55b97fe2016-01-28 05:22:45 -08002558 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002559
kwiberg55b97fe2016-01-28 05:22:45 -08002560 stats.fractionLost = statistics.fraction_lost;
2561 stats.cumulativeLost = statistics.cumulative_lost;
2562 stats.extendedMax = statistics.extended_max_sequence_number;
2563 stats.jitterSamples = statistics.jitter;
niklase@google.com470e71d2011-07-07 08:21:25 +00002564
kwiberg55b97fe2016-01-28 05:22:45 -08002565 // --- RTT
2566 stats.rttMs = GetRTT(true);
niklase@google.com470e71d2011-07-07 08:21:25 +00002567
kwiberg55b97fe2016-01-28 05:22:45 -08002568 // --- Data counters
niklase@google.com470e71d2011-07-07 08:21:25 +00002569
kwiberg55b97fe2016-01-28 05:22:45 -08002570 size_t bytesSent(0);
2571 uint32_t packetsSent(0);
2572 size_t bytesReceived(0);
2573 uint32_t packetsReceived(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00002574
kwiberg55b97fe2016-01-28 05:22:45 -08002575 if (statistician) {
2576 statistician->GetDataCounters(&bytesReceived, &packetsReceived);
2577 }
wu@webrtc.org822fbd82013-08-15 23:38:54 +00002578
kwiberg55b97fe2016-01-28 05:22:45 -08002579 if (_rtpRtcpModule->DataCountersRTP(&bytesSent, &packetsSent) != 0) {
2580 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2581 "GetRTPStatistics() failed to retrieve RTP datacounters =>"
2582 " output will not be complete");
2583 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002584
kwiberg55b97fe2016-01-28 05:22:45 -08002585 stats.bytesSent = bytesSent;
2586 stats.packetsSent = packetsSent;
2587 stats.bytesReceived = bytesReceived;
2588 stats.packetsReceived = packetsReceived;
niklase@google.com470e71d2011-07-07 08:21:25 +00002589
kwiberg55b97fe2016-01-28 05:22:45 -08002590 // --- Timestamps
2591 {
2592 rtc::CritScope lock(&ts_stats_lock_);
2593 stats.capture_start_ntp_time_ms_ = capture_start_ntp_time_ms_;
2594 }
2595 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002596}
2597
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00002598int Channel::SetCodecFECStatus(bool enable) {
2599 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2600 "Channel::SetCodecFECStatus()");
2601
kwibergc8d071e2016-04-06 12:22:38 -07002602 if (!codec_manager_.SetCodecFEC(enable) ||
2603 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00002604 _engineStatisticsPtr->SetLastError(
2605 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2606 "SetCodecFECStatus() failed to set FEC state");
2607 return -1;
2608 }
2609 return 0;
2610}
2611
2612bool Channel::GetCodecFECStatus() {
kwibergc8d071e2016-04-06 12:22:38 -07002613 return codec_manager_.GetStackParams()->use_codec_fec;
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00002614}
2615
pwestin@webrtc.orgdb249952013-06-05 15:33:20 +00002616void Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) {
2617 // None of these functions can fail.
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002618 // If pacing is enabled we always store packets.
2619 if (!pacing_enabled_)
2620 _rtpRtcpModule->SetStorePacketsStatus(enable, maxNumberOfPackets);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00002621 rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets);
pwestin@webrtc.orgd30859e2013-06-06 21:09:01 +00002622 if (enable)
andrew@webrtc.orgeb524d92013-09-23 23:02:24 +00002623 audio_coding_->EnableNack(maxNumberOfPackets);
pwestin@webrtc.orgd30859e2013-06-06 21:09:01 +00002624 else
andrew@webrtc.orgeb524d92013-09-23 23:02:24 +00002625 audio_coding_->DisableNack();
pwestin@webrtc.orgdb249952013-06-05 15:33:20 +00002626}
2627
pwestin@webrtc.orgd30859e2013-06-06 21:09:01 +00002628// Called when we are missing one or more packets.
2629int Channel::ResendPackets(const uint16_t* sequence_numbers, int length) {
pwestin@webrtc.orgdb249952013-06-05 15:33:20 +00002630 return _rtpRtcpModule->SendNACK(sequence_numbers, length);
2631}
2632
kwiberg55b97fe2016-01-28 05:22:45 -08002633uint32_t Channel::Demultiplex(const AudioFrame& audioFrame) {
2634 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2635 "Channel::Demultiplex()");
2636 _audioFrame.CopyFrom(audioFrame);
2637 _audioFrame.id_ = _channelId;
2638 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002639}
2640
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002641void Channel::Demultiplex(const int16_t* audio_data,
xians@webrtc.org8fff1f02013-07-31 16:27:42 +00002642 int sample_rate,
Peter Kastingdce40cf2015-08-24 14:52:23 -07002643 size_t number_of_frames,
Peter Kasting69558702016-01-12 16:26:35 -08002644 size_t number_of_channels) {
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002645 CodecInst codec;
2646 GetSendCodec(codec);
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002647
Alejandro Luebscdfe20b2015-09-23 12:49:12 -07002648 // Never upsample or upmix the capture signal here. This should be done at the
2649 // end of the send chain.
2650 _audioFrame.sample_rate_hz_ = std::min(codec.plfreq, sample_rate);
2651 _audioFrame.num_channels_ = std::min(number_of_channels, codec.channels);
2652 RemixAndResample(audio_data, number_of_frames, number_of_channels,
2653 sample_rate, &input_resampler_, &_audioFrame);
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002654}
2655
kwiberg55b97fe2016-01-28 05:22:45 -08002656uint32_t Channel::PrepareEncodeAndSend(int mixingFrequency) {
2657 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2658 "Channel::PrepareEncodeAndSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00002659
kwiberg55b97fe2016-01-28 05:22:45 -08002660 if (_audioFrame.samples_per_channel_ == 0) {
2661 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2662 "Channel::PrepareEncodeAndSend() invalid audio frame");
2663 return 0xFFFFFFFF;
2664 }
2665
2666 if (channel_state_.Get().input_file_playing) {
2667 MixOrReplaceAudioWithFile(mixingFrequency);
2668 }
2669
solenberg1c2af8e2016-03-24 10:36:00 -07002670 bool is_muted = InputMute(); // Cache locally as InputMute() takes a lock.
2671 AudioFrameOperations::Mute(&_audioFrame, previous_frame_muted_, is_muted);
kwiberg55b97fe2016-01-28 05:22:45 -08002672
kwiberg55b97fe2016-01-28 05:22:45 -08002673 if (_includeAudioLevelIndication) {
2674 size_t length =
2675 _audioFrame.samples_per_channel_ * _audioFrame.num_channels_;
Tommi60c4e0a2016-05-26 21:35:27 +02002676 RTC_CHECK_LE(length, sizeof(_audioFrame.data_));
solenberg1c2af8e2016-03-24 10:36:00 -07002677 if (is_muted && previous_frame_muted_) {
henrik.lundin50499422016-11-29 04:26:24 -08002678 rms_level_.AnalyzeMuted(length);
kwiberg55b97fe2016-01-28 05:22:45 -08002679 } else {
henrik.lundin50499422016-11-29 04:26:24 -08002680 rms_level_.Analyze(
2681 rtc::ArrayView<const int16_t>(_audioFrame.data_, length));
niklase@google.com470e71d2011-07-07 08:21:25 +00002682 }
kwiberg55b97fe2016-01-28 05:22:45 -08002683 }
solenberg1c2af8e2016-03-24 10:36:00 -07002684 previous_frame_muted_ = is_muted;
niklase@google.com470e71d2011-07-07 08:21:25 +00002685
kwiberg55b97fe2016-01-28 05:22:45 -08002686 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002687}
2688
kwiberg55b97fe2016-01-28 05:22:45 -08002689uint32_t Channel::EncodeAndSend() {
2690 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2691 "Channel::EncodeAndSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00002692
kwiberg55b97fe2016-01-28 05:22:45 -08002693 assert(_audioFrame.num_channels_ <= 2);
2694 if (_audioFrame.samples_per_channel_ == 0) {
2695 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2696 "Channel::EncodeAndSend() invalid audio frame");
2697 return 0xFFFFFFFF;
2698 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002699
kwiberg55b97fe2016-01-28 05:22:45 -08002700 _audioFrame.id_ = _channelId;
niklase@google.com470e71d2011-07-07 08:21:25 +00002701
kwiberg55b97fe2016-01-28 05:22:45 -08002702 // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
niklase@google.com470e71d2011-07-07 08:21:25 +00002703
kwiberg55b97fe2016-01-28 05:22:45 -08002704 // The ACM resamples internally.
2705 _audioFrame.timestamp_ = _timeStamp;
2706 // This call will trigger AudioPacketizationCallback::SendData if encoding
2707 // is done and payload is ready for packetization and transmission.
2708 // Otherwise, it will return without invoking the callback.
2709 if (audio_coding_->Add10MsData((AudioFrame&)_audioFrame) < 0) {
2710 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
2711 "Channel::EncodeAndSend() ACM encoding failed");
2712 return 0xFFFFFFFF;
2713 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002714
kwiberg55b97fe2016-01-28 05:22:45 -08002715 _timeStamp += static_cast<uint32_t>(_audioFrame.samples_per_channel_);
2716 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002717}
2718
solenberg7602aab2016-11-14 11:30:07 -08002719void Channel::set_associate_send_channel(const ChannelOwner& channel) {
2720 RTC_DCHECK(!channel.channel() ||
2721 channel.channel()->ChannelId() != _channelId);
2722 rtc::CritScope lock(&assoc_send_channel_lock_);
2723 associate_send_channel_ = channel;
2724}
2725
Minyue2013aec2015-05-13 14:14:42 +02002726void Channel::DisassociateSendChannel(int channel_id) {
tommi31fc21f2016-01-21 10:37:37 -08002727 rtc::CritScope lock(&assoc_send_channel_lock_);
Minyue2013aec2015-05-13 14:14:42 +02002728 Channel* channel = associate_send_channel_.channel();
2729 if (channel && channel->ChannelId() == channel_id) {
2730 // If this channel is associated with a send channel of the specified
2731 // Channel ID, disassociate with it.
2732 ChannelOwner ref(NULL);
2733 associate_send_channel_ = ref;
2734 }
2735}
2736
ivoc14d5dbe2016-07-04 07:06:55 -07002737void Channel::SetRtcEventLog(RtcEventLog* event_log) {
2738 event_log_proxy_->SetEventLog(event_log);
2739}
2740
michaelt9332b7d2016-11-30 07:51:13 -08002741void Channel::SetRtcpRttStats(RtcpRttStats* rtcp_rtt_stats) {
2742 rtcp_rtt_stats_proxy_->SetRtcpRttStats(rtcp_rtt_stats);
2743}
2744
nisse284542b2017-01-10 08:58:32 -08002745void Channel::UpdateOverheadForEncoder() {
2746 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
2747 if (*encoder) {
2748 (*encoder)->OnReceivedOverhead(transport_overhead_per_packet_ +
2749 rtp_overhead_per_packet_);
2750 }
2751 });
2752}
2753
2754void Channel::SetTransportOverhead(size_t transport_overhead_per_packet) {
2755 transport_overhead_per_packet_ = transport_overhead_per_packet;
2756 UpdateOverheadForEncoder();
michaelt79e05882016-11-08 02:50:09 -08002757}
2758
michaeltbf65be52016-12-15 06:24:49 -08002759void Channel::OnOverheadChanged(size_t overhead_bytes_per_packet) {
nisse284542b2017-01-10 08:58:32 -08002760 rtp_overhead_per_packet_ = overhead_bytes_per_packet;
2761 UpdateOverheadForEncoder();
michaeltbf65be52016-12-15 06:24:49 -08002762}
2763
kwiberg55b97fe2016-01-28 05:22:45 -08002764int Channel::GetNetworkStatistics(NetworkStatistics& stats) {
2765 return audio_coding_->GetNetworkStatistics(&stats);
niklase@google.com470e71d2011-07-07 08:21:25 +00002766}
2767
wu@webrtc.org24301a62013-12-13 19:17:43 +00002768void Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const {
2769 audio_coding_->GetDecodingCallStatistics(stats);
2770}
2771
solenberg358057b2015-11-27 10:46:42 -08002772uint32_t Channel::GetDelayEstimate() const {
solenberg08b19df2017-02-15 00:42:31 -08002773 rtc::CritScope lock(&video_sync_lock_);
2774 return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_;
deadbeef74375882015-08-13 12:09:10 -07002775}
2776
kwiberg55b97fe2016-01-28 05:22:45 -08002777int Channel::SetMinimumPlayoutDelay(int delayMs) {
2778 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2779 "Channel::SetMinimumPlayoutDelay()");
2780 if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
2781 (delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) {
2782 _engineStatisticsPtr->SetLastError(
2783 VE_INVALID_ARGUMENT, kTraceError,
2784 "SetMinimumPlayoutDelay() invalid min delay");
2785 return -1;
2786 }
2787 if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) {
2788 _engineStatisticsPtr->SetLastError(
2789 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2790 "SetMinimumPlayoutDelay() failed to set min playout delay");
2791 return -1;
2792 }
2793 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002794}
2795
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002796int Channel::GetPlayoutTimestamp(unsigned int& timestamp) {
deadbeef74375882015-08-13 12:09:10 -07002797 uint32_t playout_timestamp_rtp = 0;
2798 {
tommi31fc21f2016-01-21 10:37:37 -08002799 rtc::CritScope lock(&video_sync_lock_);
deadbeef74375882015-08-13 12:09:10 -07002800 playout_timestamp_rtp = playout_timestamp_rtp_;
2801 }
kwiberg55b97fe2016-01-28 05:22:45 -08002802 if (playout_timestamp_rtp == 0) {
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002803 _engineStatisticsPtr->SetLastError(
skvlad4c0536b2016-07-07 13:06:26 -07002804 VE_CANNOT_RETRIEVE_VALUE, kTraceStateInfo,
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002805 "GetPlayoutTimestamp() failed to retrieve timestamp");
2806 return -1;
2807 }
deadbeef74375882015-08-13 12:09:10 -07002808 timestamp = playout_timestamp_rtp;
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002809 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002810}
2811
kwiberg55b97fe2016-01-28 05:22:45 -08002812int Channel::GetRtpRtcp(RtpRtcp** rtpRtcpModule,
2813 RtpReceiver** rtp_receiver) const {
2814 *rtpRtcpModule = _rtpRtcpModule.get();
2815 *rtp_receiver = rtp_receiver_.get();
2816 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002817}
2818
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00002819// TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
2820// a shared helper.
kwiberg55b97fe2016-01-28 05:22:45 -08002821int32_t Channel::MixOrReplaceAudioWithFile(int mixingFrequency) {
kwibergb7f89d62016-02-17 10:04:18 -08002822 std::unique_ptr<int16_t[]> fileBuffer(new int16_t[640]);
kwiberg55b97fe2016-01-28 05:22:45 -08002823 size_t fileSamples(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00002824
kwiberg55b97fe2016-01-28 05:22:45 -08002825 {
2826 rtc::CritScope cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002827
kwiberg5a25d952016-08-17 07:31:12 -07002828 if (!input_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002829 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2830 "Channel::MixOrReplaceAudioWithFile() fileplayer"
2831 " doesnt exist");
2832 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002833 }
2834
kwiberg4ec01d92016-08-22 08:43:54 -07002835 if (input_file_player_->Get10msAudioFromFile(fileBuffer.get(), &fileSamples,
kwiberg5a25d952016-08-17 07:31:12 -07002836 mixingFrequency) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08002837 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2838 "Channel::MixOrReplaceAudioWithFile() file mixing "
2839 "failed");
2840 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002841 }
kwiberg55b97fe2016-01-28 05:22:45 -08002842 if (fileSamples == 0) {
2843 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2844 "Channel::MixOrReplaceAudioWithFile() file is ended");
2845 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002846 }
kwiberg55b97fe2016-01-28 05:22:45 -08002847 }
2848
2849 assert(_audioFrame.samples_per_channel_ == fileSamples);
2850
2851 if (_mixFileWithMicrophone) {
2852 // Currently file stream is always mono.
2853 // TODO(xians): Change the code when FilePlayer supports real stereo.
2854 MixWithSat(_audioFrame.data_, _audioFrame.num_channels_, fileBuffer.get(),
2855 1, fileSamples);
2856 } else {
2857 // Replace ACM audio with file.
2858 // Currently file stream is always mono.
2859 // TODO(xians): Change the code when FilePlayer supports real stereo.
2860 _audioFrame.UpdateFrame(
2861 _channelId, 0xFFFFFFFF, fileBuffer.get(), fileSamples, mixingFrequency,
2862 AudioFrame::kNormalSpeech, AudioFrame::kVadUnknown, 1);
2863 }
2864 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002865}
2866
kwiberg55b97fe2016-01-28 05:22:45 -08002867int32_t Channel::MixAudioWithFile(AudioFrame& audioFrame, int mixingFrequency) {
2868 assert(mixingFrequency <= 48000);
niklase@google.com470e71d2011-07-07 08:21:25 +00002869
kwibergb7f89d62016-02-17 10:04:18 -08002870 std::unique_ptr<int16_t[]> fileBuffer(new int16_t[960]);
kwiberg55b97fe2016-01-28 05:22:45 -08002871 size_t fileSamples(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00002872
kwiberg55b97fe2016-01-28 05:22:45 -08002873 {
2874 rtc::CritScope cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002875
kwiberg5a25d952016-08-17 07:31:12 -07002876 if (!output_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002877 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2878 "Channel::MixAudioWithFile() file mixing failed");
2879 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002880 }
2881
kwiberg55b97fe2016-01-28 05:22:45 -08002882 // We should get the frequency we ask for.
kwiberg4ec01d92016-08-22 08:43:54 -07002883 if (output_file_player_->Get10msAudioFromFile(
2884 fileBuffer.get(), &fileSamples, mixingFrequency) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08002885 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2886 "Channel::MixAudioWithFile() file mixing failed");
2887 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002888 }
kwiberg55b97fe2016-01-28 05:22:45 -08002889 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002890
kwiberg55b97fe2016-01-28 05:22:45 -08002891 if (audioFrame.samples_per_channel_ == fileSamples) {
2892 // Currently file stream is always mono.
2893 // TODO(xians): Change the code when FilePlayer supports real stereo.
2894 MixWithSat(audioFrame.data_, audioFrame.num_channels_, fileBuffer.get(), 1,
2895 fileSamples);
2896 } else {
2897 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2898 "Channel::MixAudioWithFile() samples_per_channel_(%" PRIuS
2899 ") != "
2900 "fileSamples(%" PRIuS ")",
2901 audioFrame.samples_per_channel_, fileSamples);
2902 return -1;
2903 }
2904
2905 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002906}
2907
deadbeef74375882015-08-13 12:09:10 -07002908void Channel::UpdatePlayoutTimestamp(bool rtcp) {
henrik.lundin96bd5022016-04-06 04:13:56 -07002909 jitter_buffer_playout_timestamp_ = audio_coding_->PlayoutTimestamp();
deadbeef74375882015-08-13 12:09:10 -07002910
henrik.lundin96bd5022016-04-06 04:13:56 -07002911 if (!jitter_buffer_playout_timestamp_) {
2912 // This can happen if this channel has not received any RTP packets. In
2913 // this case, NetEq is not capable of computing a playout timestamp.
deadbeef74375882015-08-13 12:09:10 -07002914 return;
2915 }
2916
2917 uint16_t delay_ms = 0;
2918 if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08002919 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
deadbeef74375882015-08-13 12:09:10 -07002920 "Channel::UpdatePlayoutTimestamp() failed to read playout"
2921 " delay from the ADM");
2922 _engineStatisticsPtr->SetLastError(
2923 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
2924 "UpdatePlayoutTimestamp() failed to retrieve playout delay");
2925 return;
2926 }
2927
henrik.lundin96bd5022016-04-06 04:13:56 -07002928 RTC_DCHECK(jitter_buffer_playout_timestamp_);
2929 uint32_t playout_timestamp = *jitter_buffer_playout_timestamp_;
deadbeef74375882015-08-13 12:09:10 -07002930
2931 // Remove the playout delay.
ossue280cde2016-10-12 11:04:10 -07002932 playout_timestamp -= (delay_ms * (GetRtpTimestampRateHz() / 1000));
deadbeef74375882015-08-13 12:09:10 -07002933
kwiberg55b97fe2016-01-28 05:22:45 -08002934 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
deadbeef74375882015-08-13 12:09:10 -07002935 "Channel::UpdatePlayoutTimestamp() => playoutTimestamp = %lu",
henrik.lundin96bd5022016-04-06 04:13:56 -07002936 playout_timestamp);
deadbeef74375882015-08-13 12:09:10 -07002937
2938 {
tommi31fc21f2016-01-21 10:37:37 -08002939 rtc::CritScope lock(&video_sync_lock_);
solenberg81d93f32017-02-14 03:44:57 -08002940 if (!rtcp) {
henrik.lundin96bd5022016-04-06 04:13:56 -07002941 playout_timestamp_rtp_ = playout_timestamp;
deadbeef74375882015-08-13 12:09:10 -07002942 }
2943 playout_delay_ms_ = delay_ms;
2944 }
2945}
2946
kwiberg55b97fe2016-01-28 05:22:45 -08002947void Channel::RegisterReceiveCodecsToRTPModule() {
2948 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2949 "Channel::RegisterReceiveCodecsToRTPModule()");
niklase@google.com470e71d2011-07-07 08:21:25 +00002950
kwiberg55b97fe2016-01-28 05:22:45 -08002951 CodecInst codec;
2952 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
niklase@google.com470e71d2011-07-07 08:21:25 +00002953
kwiberg55b97fe2016-01-28 05:22:45 -08002954 for (int idx = 0; idx < nSupportedCodecs; idx++) {
2955 // Open up the RTP/RTCP receiver for all supported codecs
2956 if ((audio_coding_->Codec(idx, &codec) == -1) ||
magjed56124bd2016-11-24 09:34:46 -08002957 (rtp_receiver_->RegisterReceivePayload(codec) == -1)) {
kwiberg55b97fe2016-01-28 05:22:45 -08002958 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2959 "Channel::RegisterReceiveCodecsToRTPModule() unable"
2960 " to register %s (%d/%d/%" PRIuS
2961 "/%d) to RTP/RTCP "
2962 "receiver",
2963 codec.plname, codec.pltype, codec.plfreq, codec.channels,
2964 codec.rate);
2965 } else {
2966 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2967 "Channel::RegisterReceiveCodecsToRTPModule() %s "
2968 "(%d/%d/%" PRIuS
2969 "/%d) has been added to the RTP/RTCP "
2970 "receiver",
2971 codec.plname, codec.pltype, codec.plfreq, codec.channels,
2972 codec.rate);
niklase@google.com470e71d2011-07-07 08:21:25 +00002973 }
kwiberg55b97fe2016-01-28 05:22:45 -08002974 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002975}
2976
kwiberg55b97fe2016-01-28 05:22:45 -08002977int Channel::SetSendRtpHeaderExtension(bool enable,
2978 RTPExtensionType type,
wu@webrtc.orgebdb0e32014-03-06 23:49:08 +00002979 unsigned char id) {
2980 int error = 0;
2981 _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type);
2982 if (enable) {
2983 error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(type, id);
2984 }
2985 return error;
2986}
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00002987
ossue280cde2016-10-12 11:04:10 -07002988int Channel::GetRtpTimestampRateHz() const {
2989 const auto format = audio_coding_->ReceiveFormat();
2990 // Default to the playout frequency if we've not gotten any packets yet.
2991 // TODO(ossu): Zero clockrate can only happen if we've added an external
2992 // decoder for a format we don't support internally. Remove once that way of
2993 // adding decoders is gone!
2994 return (format && format->clockrate_hz != 0)
2995 ? format->clockrate_hz
2996 : audio_coding_->PlayoutFrequency();
wu@webrtc.org94454b72014-06-05 20:34:08 +00002997}
2998
Minyue2013aec2015-05-13 14:14:42 +02002999int64_t Channel::GetRTT(bool allow_associate_channel) const {
pbosda903ea2015-10-02 02:36:56 -07003000 RtcpMode method = _rtpRtcpModule->RTCP();
3001 if (method == RtcpMode::kOff) {
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003002 return 0;
3003 }
3004 std::vector<RTCPReportBlock> report_blocks;
3005 _rtpRtcpModule->RemoteRTCPStat(&report_blocks);
Minyue2013aec2015-05-13 14:14:42 +02003006
3007 int64_t rtt = 0;
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003008 if (report_blocks.empty()) {
Minyue2013aec2015-05-13 14:14:42 +02003009 if (allow_associate_channel) {
tommi31fc21f2016-01-21 10:37:37 -08003010 rtc::CritScope lock(&assoc_send_channel_lock_);
Minyue2013aec2015-05-13 14:14:42 +02003011 Channel* channel = associate_send_channel_.channel();
3012 // Tries to get RTT from an associated channel. This is important for
3013 // receive-only channels.
3014 if (channel) {
3015 // To prevent infinite recursion and deadlock, calling GetRTT of
3016 // associate channel should always use "false" for argument:
3017 // |allow_associate_channel|.
3018 rtt = channel->GetRTT(false);
3019 }
3020 }
3021 return rtt;
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003022 }
3023
3024 uint32_t remoteSSRC = rtp_receiver_->SSRC();
3025 std::vector<RTCPReportBlock>::const_iterator it = report_blocks.begin();
3026 for (; it != report_blocks.end(); ++it) {
3027 if (it->remoteSSRC == remoteSSRC)
3028 break;
3029 }
3030 if (it == report_blocks.end()) {
3031 // We have not received packets with SSRC matching the report blocks.
3032 // To calculate RTT we try with the SSRC of the first report block.
3033 // This is very important for send-only channels where we don't know
3034 // the SSRC of the other end.
3035 remoteSSRC = report_blocks[0].remoteSSRC;
3036 }
Minyue2013aec2015-05-13 14:14:42 +02003037
pkasting@chromium.org16825b12015-01-12 21:51:21 +00003038 int64_t avg_rtt = 0;
kwiberg55b97fe2016-01-28 05:22:45 -08003039 int64_t max_rtt = 0;
pkasting@chromium.org16825b12015-01-12 21:51:21 +00003040 int64_t min_rtt = 0;
kwiberg55b97fe2016-01-28 05:22:45 -08003041 if (_rtpRtcpModule->RTT(remoteSSRC, &rtt, &avg_rtt, &min_rtt, &max_rtt) !=
3042 0) {
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003043 return 0;
3044 }
pkasting@chromium.org16825b12015-01-12 21:51:21 +00003045 return rtt;
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003046}
3047
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00003048} // namespace voe
3049} // namespace webrtc