blob: 0573245aeee46ff1884632dbd7c2ad5ac4be7a41 [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"
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +000042#include "webrtc/voice_engine/utility.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000043
andrew@webrtc.org50419b02012-11-14 19:07:54 +000044namespace webrtc {
45namespace voe {
niklase@google.com470e71d2011-07-07 08:21:25 +000046
kwibergc8d071e2016-04-06 12:22:38 -070047namespace {
48
Erik Språng737336d2016-07-29 12:59:36 +020049constexpr int64_t kMaxRetransmissionWindowMs = 1000;
50constexpr int64_t kMinRetransmissionWindowMs = 30;
51
kwibergc8d071e2016-04-06 12:22:38 -070052} // namespace
53
solenberg8842c3e2016-03-11 03:06:41 -080054const int kTelephoneEventAttenuationdB = 10;
55
ivoc14d5dbe2016-07-04 07:06:55 -070056class RtcEventLogProxy final : public webrtc::RtcEventLog {
57 public:
58 RtcEventLogProxy() : event_log_(nullptr) {}
59
60 bool StartLogging(const std::string& file_name,
61 int64_t max_size_bytes) override {
62 RTC_NOTREACHED();
63 return false;
64 }
65
66 bool StartLogging(rtc::PlatformFile log_file,
67 int64_t max_size_bytes) override {
68 RTC_NOTREACHED();
69 return false;
70 }
71
72 void StopLogging() override { RTC_NOTREACHED(); }
73
74 void LogVideoReceiveStreamConfig(
75 const webrtc::VideoReceiveStream::Config& config) override {
76 rtc::CritScope lock(&crit_);
77 if (event_log_) {
78 event_log_->LogVideoReceiveStreamConfig(config);
79 }
80 }
81
82 void LogVideoSendStreamConfig(
83 const webrtc::VideoSendStream::Config& config) override {
84 rtc::CritScope lock(&crit_);
85 if (event_log_) {
86 event_log_->LogVideoSendStreamConfig(config);
87 }
88 }
89
ivoce0928d82016-10-10 05:12:51 -070090 void LogAudioReceiveStreamConfig(
91 const webrtc::AudioReceiveStream::Config& config) override {
92 rtc::CritScope lock(&crit_);
93 if (event_log_) {
94 event_log_->LogAudioReceiveStreamConfig(config);
95 }
96 }
97
98 void LogAudioSendStreamConfig(
99 const webrtc::AudioSendStream::Config& config) override {
100 rtc::CritScope lock(&crit_);
101 if (event_log_) {
102 event_log_->LogAudioSendStreamConfig(config);
103 }
104 }
105
ivoc14d5dbe2016-07-04 07:06:55 -0700106 void LogRtpHeader(webrtc::PacketDirection direction,
107 webrtc::MediaType media_type,
108 const uint8_t* header,
109 size_t packet_length) override {
philipel32d00102017-02-27 02:18:46 -0800110 LogRtpHeader(direction, media_type, header, packet_length,
111 PacedPacketInfo::kNotAProbe);
112 }
113
114 void LogRtpHeader(webrtc::PacketDirection direction,
115 webrtc::MediaType media_type,
116 const uint8_t* header,
117 size_t packet_length,
118 int probe_cluster_id) override {
ivoc14d5dbe2016-07-04 07:06:55 -0700119 rtc::CritScope lock(&crit_);
120 if (event_log_) {
philipel32d00102017-02-27 02:18:46 -0800121 event_log_->LogRtpHeader(direction, media_type, header, packet_length,
122 probe_cluster_id);
ivoc14d5dbe2016-07-04 07:06:55 -0700123 }
124 }
125
126 void LogRtcpPacket(webrtc::PacketDirection direction,
127 webrtc::MediaType media_type,
128 const uint8_t* packet,
129 size_t length) override {
130 rtc::CritScope lock(&crit_);
131 if (event_log_) {
132 event_log_->LogRtcpPacket(direction, media_type, packet, length);
133 }
134 }
135
136 void LogAudioPlayout(uint32_t ssrc) override {
137 rtc::CritScope lock(&crit_);
138 if (event_log_) {
139 event_log_->LogAudioPlayout(ssrc);
140 }
141 }
142
terelius424e6cf2017-02-20 05:14:41 -0800143 void LogLossBasedBweUpdate(int32_t bitrate_bps,
ivoc14d5dbe2016-07-04 07:06:55 -0700144 uint8_t fraction_loss,
145 int32_t total_packets) override {
146 rtc::CritScope lock(&crit_);
147 if (event_log_) {
terelius424e6cf2017-02-20 05:14:41 -0800148 event_log_->LogLossBasedBweUpdate(bitrate_bps, fraction_loss,
149 total_packets);
ivoc14d5dbe2016-07-04 07:06:55 -0700150 }
151 }
152
terelius424e6cf2017-02-20 05:14:41 -0800153 void LogDelayBasedBweUpdate(int32_t bitrate_bps,
terelius0baf55d2017-02-17 03:38:28 -0800154 BandwidthUsage detector_state) override {
155 rtc::CritScope lock(&crit_);
156 if (event_log_) {
terelius424e6cf2017-02-20 05:14:41 -0800157 event_log_->LogDelayBasedBweUpdate(bitrate_bps, detector_state);
terelius0baf55d2017-02-17 03:38:28 -0800158 }
159 }
160
minyue4b7c9522017-01-24 04:54:59 -0800161 void LogAudioNetworkAdaptation(
162 const AudioNetworkAdaptor::EncoderRuntimeConfig& config) override {
163 rtc::CritScope lock(&crit_);
164 if (event_log_) {
165 event_log_->LogAudioNetworkAdaptation(config);
166 }
167 }
168
philipel32d00102017-02-27 02:18:46 -0800169 void LogProbeClusterCreated(int id,
170 int bitrate_bps,
171 int min_probes,
172 int min_bytes) override {
173 rtc::CritScope lock(&crit_);
174 if (event_log_) {
175 event_log_->LogProbeClusterCreated(id, bitrate_bps, min_probes,
176 min_bytes);
177 }
178 };
179
180 void LogProbeResultSuccess(int id, int bitrate_bps) override {
181 rtc::CritScope lock(&crit_);
182 if (event_log_) {
183 event_log_->LogProbeResultSuccess(id, bitrate_bps);
184 }
185 };
186
187 void LogProbeResultFailure(int id,
188 ProbeFailureReason failure_reason) override {
189 rtc::CritScope lock(&crit_);
190 if (event_log_) {
191 event_log_->LogProbeResultFailure(id, failure_reason);
192 }
193 };
194
ivoc14d5dbe2016-07-04 07:06:55 -0700195 void SetEventLog(RtcEventLog* event_log) {
196 rtc::CritScope lock(&crit_);
197 event_log_ = event_log;
198 }
199
200 private:
201 rtc::CriticalSection crit_;
202 RtcEventLog* event_log_ GUARDED_BY(crit_);
203 RTC_DISALLOW_COPY_AND_ASSIGN(RtcEventLogProxy);
204};
205
michaelt9332b7d2016-11-30 07:51:13 -0800206class RtcpRttStatsProxy final : public RtcpRttStats {
207 public:
208 RtcpRttStatsProxy() : rtcp_rtt_stats_(nullptr) {}
209
210 void OnRttUpdate(int64_t rtt) override {
211 rtc::CritScope lock(&crit_);
212 if (rtcp_rtt_stats_)
213 rtcp_rtt_stats_->OnRttUpdate(rtt);
214 }
215
216 int64_t LastProcessedRtt() const override {
217 rtc::CritScope lock(&crit_);
218 if (!rtcp_rtt_stats_)
219 return 0;
220 return rtcp_rtt_stats_->LastProcessedRtt();
221 }
222
223 void SetRtcpRttStats(RtcpRttStats* rtcp_rtt_stats) {
224 rtc::CritScope lock(&crit_);
225 rtcp_rtt_stats_ = rtcp_rtt_stats;
226 }
227
228 private:
229 rtc::CriticalSection crit_;
230 RtcpRttStats* rtcp_rtt_stats_ GUARDED_BY(crit_);
231 RTC_DISALLOW_COPY_AND_ASSIGN(RtcpRttStatsProxy);
232};
233
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100234class TransportFeedbackProxy : public TransportFeedbackObserver {
235 public:
236 TransportFeedbackProxy() : feedback_observer_(nullptr) {
237 pacer_thread_.DetachFromThread();
238 network_thread_.DetachFromThread();
239 }
240
241 void SetTransportFeedbackObserver(
242 TransportFeedbackObserver* feedback_observer) {
243 RTC_DCHECK(thread_checker_.CalledOnValidThread());
244 rtc::CritScope lock(&crit_);
245 feedback_observer_ = feedback_observer;
246 }
247
248 // Implements TransportFeedbackObserver.
249 void AddPacket(uint16_t sequence_number,
250 size_t length,
philipel8aadd502017-02-23 02:56:13 -0800251 const PacedPacketInfo& pacing_info) override {
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100252 RTC_DCHECK(pacer_thread_.CalledOnValidThread());
253 rtc::CritScope lock(&crit_);
254 if (feedback_observer_)
philipel8aadd502017-02-23 02:56:13 -0800255 feedback_observer_->AddPacket(sequence_number, length, pacing_info);
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100256 }
philipel8aadd502017-02-23 02:56:13 -0800257
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100258 void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override {
259 RTC_DCHECK(network_thread_.CalledOnValidThread());
260 rtc::CritScope lock(&crit_);
michaelt9960bb12016-10-18 09:40:34 -0700261 if (feedback_observer_)
262 feedback_observer_->OnTransportFeedback(feedback);
Stefan Holmer60e43462016-09-07 09:58:20 +0200263 }
264 std::vector<PacketInfo> GetTransportFeedbackVector() const override {
265 RTC_NOTREACHED();
266 return std::vector<PacketInfo>();
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100267 }
268
269 private:
270 rtc::CriticalSection crit_;
271 rtc::ThreadChecker thread_checker_;
272 rtc::ThreadChecker pacer_thread_;
273 rtc::ThreadChecker network_thread_;
274 TransportFeedbackObserver* feedback_observer_ GUARDED_BY(&crit_);
275};
276
277class TransportSequenceNumberProxy : public TransportSequenceNumberAllocator {
278 public:
279 TransportSequenceNumberProxy() : seq_num_allocator_(nullptr) {
280 pacer_thread_.DetachFromThread();
281 }
282
283 void SetSequenceNumberAllocator(
284 TransportSequenceNumberAllocator* seq_num_allocator) {
285 RTC_DCHECK(thread_checker_.CalledOnValidThread());
286 rtc::CritScope lock(&crit_);
287 seq_num_allocator_ = seq_num_allocator;
288 }
289
290 // Implements TransportSequenceNumberAllocator.
291 uint16_t AllocateSequenceNumber() override {
292 RTC_DCHECK(pacer_thread_.CalledOnValidThread());
293 rtc::CritScope lock(&crit_);
294 if (!seq_num_allocator_)
295 return 0;
296 return seq_num_allocator_->AllocateSequenceNumber();
297 }
298
299 private:
300 rtc::CriticalSection crit_;
301 rtc::ThreadChecker thread_checker_;
302 rtc::ThreadChecker pacer_thread_;
303 TransportSequenceNumberAllocator* seq_num_allocator_ GUARDED_BY(&crit_);
304};
305
306class RtpPacketSenderProxy : public RtpPacketSender {
307 public:
kwiberg55b97fe2016-01-28 05:22:45 -0800308 RtpPacketSenderProxy() : rtp_packet_sender_(nullptr) {}
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100309
310 void SetPacketSender(RtpPacketSender* rtp_packet_sender) {
311 RTC_DCHECK(thread_checker_.CalledOnValidThread());
312 rtc::CritScope lock(&crit_);
313 rtp_packet_sender_ = rtp_packet_sender;
314 }
315
316 // Implements RtpPacketSender.
317 void InsertPacket(Priority priority,
318 uint32_t ssrc,
319 uint16_t sequence_number,
320 int64_t capture_time_ms,
321 size_t bytes,
322 bool retransmission) override {
323 rtc::CritScope lock(&crit_);
324 if (rtp_packet_sender_) {
325 rtp_packet_sender_->InsertPacket(priority, ssrc, sequence_number,
326 capture_time_ms, bytes, retransmission);
327 }
328 }
329
330 private:
331 rtc::ThreadChecker thread_checker_;
332 rtc::CriticalSection crit_;
333 RtpPacketSender* rtp_packet_sender_ GUARDED_BY(&crit_);
334};
335
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000336class VoERtcpObserver : public RtcpBandwidthObserver {
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000337 public:
stefan7de8d642017-02-07 07:14:08 -0800338 explicit VoERtcpObserver(Channel* owner)
339 : owner_(owner), bandwidth_observer_(nullptr) {}
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000340 virtual ~VoERtcpObserver() {}
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000341
stefan7de8d642017-02-07 07:14:08 -0800342 void SetBandwidthObserver(RtcpBandwidthObserver* bandwidth_observer) {
343 rtc::CritScope lock(&crit_);
344 bandwidth_observer_ = bandwidth_observer;
345 }
346
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000347 void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
stefan7de8d642017-02-07 07:14:08 -0800348 rtc::CritScope lock(&crit_);
349 if (bandwidth_observer_) {
350 bandwidth_observer_->OnReceivedEstimatedBitrate(bitrate);
351 }
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000352 }
353
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000354 void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
355 int64_t rtt,
356 int64_t now_ms) override {
stefan7de8d642017-02-07 07:14:08 -0800357 {
358 rtc::CritScope lock(&crit_);
359 if (bandwidth_observer_) {
360 bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, rtt,
361 now_ms);
362 }
363 }
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000364 // TODO(mflodman): Do we need to aggregate reports here or can we jut send
365 // what we get? I.e. do we ever get multiple reports bundled into one RTCP
366 // report for VoiceEngine?
367 if (report_blocks.empty())
368 return;
369
370 int fraction_lost_aggregate = 0;
371 int total_number_of_packets = 0;
372
373 // If receiving multiple report blocks, calculate the weighted average based
374 // on the number of packets a report refers to.
375 for (ReportBlockList::const_iterator block_it = report_blocks.begin();
376 block_it != report_blocks.end(); ++block_it) {
377 // Find the previous extended high sequence number for this remote SSRC,
378 // to calculate the number of RTP packets this report refers to. Ignore if
379 // we haven't seen this SSRC before.
380 std::map<uint32_t, uint32_t>::iterator seq_num_it =
381 extended_max_sequence_number_.find(block_it->sourceSSRC);
382 int number_of_packets = 0;
383 if (seq_num_it != extended_max_sequence_number_.end()) {
384 number_of_packets = block_it->extendedHighSeqNum - seq_num_it->second;
385 }
386 fraction_lost_aggregate += number_of_packets * block_it->fractionLost;
387 total_number_of_packets += number_of_packets;
388
389 extended_max_sequence_number_[block_it->sourceSSRC] =
390 block_it->extendedHighSeqNum;
391 }
392 int weighted_fraction_lost = 0;
393 if (total_number_of_packets > 0) {
kwiberg55b97fe2016-01-28 05:22:45 -0800394 weighted_fraction_lost =
395 (fraction_lost_aggregate + total_number_of_packets / 2) /
396 total_number_of_packets;
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000397 }
398 owner_->OnIncomingFractionLoss(weighted_fraction_lost);
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000399 }
400
401 private:
402 Channel* owner_;
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000403 // Maps remote side ssrc to extended highest sequence number received.
404 std::map<uint32_t, uint32_t> extended_max_sequence_number_;
stefan7de8d642017-02-07 07:14:08 -0800405 rtc::CriticalSection crit_;
406 RtcpBandwidthObserver* bandwidth_observer_ GUARDED_BY(crit_);
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000407};
408
kwiberg55b97fe2016-01-28 05:22:45 -0800409int32_t Channel::SendData(FrameType frameType,
410 uint8_t payloadType,
411 uint32_t timeStamp,
412 const uint8_t* payloadData,
413 size_t payloadSize,
414 const RTPFragmentationHeader* fragmentation) {
415 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
416 "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u,"
417 " payloadSize=%" PRIuS ", fragmentation=0x%x)",
418 frameType, payloadType, timeStamp, payloadSize, fragmentation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000419
kwiberg55b97fe2016-01-28 05:22:45 -0800420 if (_includeAudioLevelIndication) {
421 // Store current audio level in the RTP/RTCP module.
422 // The level will be used in combination with voice-activity state
423 // (frameType) to add an RTP header extension
henrik.lundin50499422016-11-29 04:26:24 -0800424 _rtpRtcpModule->SetAudioLevel(rms_level_.Average());
kwiberg55b97fe2016-01-28 05:22:45 -0800425 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
kwiberg55b97fe2016-01-28 05:22:45 -0800427 // Push data from ACM to RTP/RTCP-module to deliver audio frame for
428 // packetization.
429 // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700430 if (!_rtpRtcpModule->SendOutgoingData(
kwiberg55b97fe2016-01-28 05:22:45 -0800431 (FrameType&)frameType, payloadType, timeStamp,
432 // Leaving the time when this frame was
433 // received from the capture device as
434 // undefined for voice for now.
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700435 -1, payloadData, payloadSize, fragmentation, nullptr, nullptr)) {
kwiberg55b97fe2016-01-28 05:22:45 -0800436 _engineStatisticsPtr->SetLastError(
437 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
438 "Channel::SendData() failed to send data to RTP/RTCP module");
439 return -1;
440 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000441
kwiberg55b97fe2016-01-28 05:22:45 -0800442 _lastLocalTimeStamp = timeStamp;
443 _lastPayloadType = payloadType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000444
kwiberg55b97fe2016-01-28 05:22:45 -0800445 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000446}
447
kwiberg55b97fe2016-01-28 05:22:45 -0800448int32_t Channel::InFrameType(FrameType frame_type) {
449 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
450 "Channel::InFrameType(frame_type=%d)", frame_type);
niklase@google.com470e71d2011-07-07 08:21:25 +0000451
kwiberg55b97fe2016-01-28 05:22:45 -0800452 rtc::CritScope cs(&_callbackCritSect);
453 _sendFrameType = (frame_type == kAudioFrameSpeech);
454 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000455}
456
stefan1d8a5062015-10-02 03:39:33 -0700457bool Channel::SendRtp(const uint8_t* data,
458 size_t len,
459 const PacketOptions& options) {
kwiberg55b97fe2016-01-28 05:22:45 -0800460 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
461 "Channel::SendPacket(channel=%d, len=%" PRIuS ")", len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000462
kwiberg55b97fe2016-01-28 05:22:45 -0800463 rtc::CritScope cs(&_callbackCritSect);
wu@webrtc.orgfb648da2013-10-18 21:10:51 +0000464
kwiberg55b97fe2016-01-28 05:22:45 -0800465 if (_transportPtr == NULL) {
466 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
467 "Channel::SendPacket() failed to send RTP packet due to"
468 " invalid transport object");
469 return false;
470 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000471
kwiberg55b97fe2016-01-28 05:22:45 -0800472 uint8_t* bufferToSendPtr = (uint8_t*)data;
473 size_t bufferLength = len;
niklase@google.com470e71d2011-07-07 08:21:25 +0000474
kwiberg55b97fe2016-01-28 05:22:45 -0800475 if (!_transportPtr->SendRtp(bufferToSendPtr, bufferLength, options)) {
476 std::string transport_name =
477 _externalTransport ? "external transport" : "WebRtc sockets";
478 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
479 "Channel::SendPacket() RTP transmission using %s failed",
480 transport_name.c_str());
481 return false;
482 }
483 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000484}
485
kwiberg55b97fe2016-01-28 05:22:45 -0800486bool Channel::SendRtcp(const uint8_t* data, size_t len) {
487 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
488 "Channel::SendRtcp(len=%" PRIuS ")", len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000489
kwiberg55b97fe2016-01-28 05:22:45 -0800490 rtc::CritScope cs(&_callbackCritSect);
491 if (_transportPtr == NULL) {
492 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
493 "Channel::SendRtcp() failed to send RTCP packet"
494 " due to invalid transport object");
495 return false;
496 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000497
kwiberg55b97fe2016-01-28 05:22:45 -0800498 uint8_t* bufferToSendPtr = (uint8_t*)data;
499 size_t bufferLength = len;
niklase@google.com470e71d2011-07-07 08:21:25 +0000500
kwiberg55b97fe2016-01-28 05:22:45 -0800501 int n = _transportPtr->SendRtcp(bufferToSendPtr, bufferLength);
502 if (n < 0) {
503 std::string transport_name =
504 _externalTransport ? "external transport" : "WebRtc sockets";
505 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
506 "Channel::SendRtcp() transmission using %s failed",
507 transport_name.c_str());
508 return false;
509 }
510 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000511}
512
kwiberg55b97fe2016-01-28 05:22:45 -0800513void Channel::OnIncomingSSRCChanged(uint32_t ssrc) {
514 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
515 "Channel::OnIncomingSSRCChanged(SSRC=%d)", ssrc);
niklase@google.com470e71d2011-07-07 08:21:25 +0000516
kwiberg55b97fe2016-01-28 05:22:45 -0800517 // Update ssrc so that NTP for AV sync can be updated.
518 _rtpRtcpModule->SetRemoteSSRC(ssrc);
niklase@google.com470e71d2011-07-07 08:21:25 +0000519}
520
Peter Boströmac547a62015-09-17 23:03:57 +0200521void Channel::OnIncomingCSRCChanged(uint32_t CSRC, bool added) {
522 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
523 "Channel::OnIncomingCSRCChanged(CSRC=%d, added=%d)", CSRC,
524 added);
niklase@google.com470e71d2011-07-07 08:21:25 +0000525}
526
Peter Boströmac547a62015-09-17 23:03:57 +0200527int32_t Channel::OnInitializeDecoder(
pbos@webrtc.org92135212013-05-14 08:31:39 +0000528 int8_t payloadType,
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +0000529 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
pbos@webrtc.org92135212013-05-14 08:31:39 +0000530 int frequency,
Peter Kasting69558702016-01-12 16:26:35 -0800531 size_t channels,
Peter Boströmac547a62015-09-17 23:03:57 +0200532 uint32_t rate) {
kwiberg55b97fe2016-01-28 05:22:45 -0800533 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
534 "Channel::OnInitializeDecoder(payloadType=%d, "
535 "payloadName=%s, frequency=%u, channels=%" PRIuS ", rate=%u)",
536 payloadType, payloadName, frequency, channels, rate);
niklase@google.com470e71d2011-07-07 08:21:25 +0000537
kwiberg55b97fe2016-01-28 05:22:45 -0800538 CodecInst receiveCodec = {0};
539 CodecInst dummyCodec = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +0000540
kwiberg55b97fe2016-01-28 05:22:45 -0800541 receiveCodec.pltype = payloadType;
542 receiveCodec.plfreq = frequency;
543 receiveCodec.channels = channels;
544 receiveCodec.rate = rate;
545 strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +0000546
kwiberg55b97fe2016-01-28 05:22:45 -0800547 audio_coding_->Codec(payloadName, &dummyCodec, frequency, channels);
548 receiveCodec.pacsize = dummyCodec.pacsize;
niklase@google.com470e71d2011-07-07 08:21:25 +0000549
kwiberg55b97fe2016-01-28 05:22:45 -0800550 // Register the new codec to the ACM
kwibergda2bf4e2016-10-24 13:47:09 -0700551 if (!audio_coding_->RegisterReceiveCodec(receiveCodec.pltype,
552 CodecInstToSdp(receiveCodec))) {
kwiberg55b97fe2016-01-28 05:22:45 -0800553 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
554 "Channel::OnInitializeDecoder() invalid codec ("
555 "pt=%d, name=%s) received - 1",
556 payloadType, payloadName);
557 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR);
558 return -1;
559 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000560
kwiberg55b97fe2016-01-28 05:22:45 -0800561 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000562}
563
kwiberg55b97fe2016-01-28 05:22:45 -0800564int32_t Channel::OnReceivedPayloadData(const uint8_t* payloadData,
565 size_t payloadSize,
566 const WebRtcRTPHeader* rtpHeader) {
567 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
568 "Channel::OnReceivedPayloadData(payloadSize=%" PRIuS
569 ","
570 " payloadType=%u, audioChannel=%" PRIuS ")",
571 payloadSize, rtpHeader->header.payloadType,
572 rtpHeader->type.Audio.channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000573
kwiberg55b97fe2016-01-28 05:22:45 -0800574 if (!channel_state_.Get().playing) {
575 // Avoid inserting into NetEQ when we are not playing. Count the
576 // packet as discarded.
577 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
578 "received packet is discarded since playing is not"
579 " activated");
niklase@google.com470e71d2011-07-07 08:21:25 +0000580 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -0800581 }
582
583 // Push the incoming payload (parsed and ready for decoding) into the ACM
584 if (audio_coding_->IncomingPacket(payloadData, payloadSize, *rtpHeader) !=
585 0) {
586 _engineStatisticsPtr->SetLastError(
587 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
588 "Channel::OnReceivedPayloadData() unable to push data to the ACM");
589 return -1;
590 }
591
kwiberg55b97fe2016-01-28 05:22:45 -0800592 int64_t round_trip_time = 0;
593 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), &round_trip_time, NULL, NULL,
594 NULL);
595
596 std::vector<uint16_t> nack_list = audio_coding_->GetNackList(round_trip_time);
597 if (!nack_list.empty()) {
598 // Can't use nack_list.data() since it's not supported by all
599 // compilers.
600 ResendPackets(&(nack_list[0]), static_cast<int>(nack_list.size()));
601 }
602 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000603}
604
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000605bool Channel::OnRecoveredPacket(const uint8_t* rtp_packet,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000606 size_t rtp_packet_length) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000607 RTPHeader header;
608 if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
609 WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVoice, _channelId,
610 "IncomingPacket invalid RTP header");
611 return false;
612 }
613 header.payload_type_frequency =
614 rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
615 if (header.payload_type_frequency < 0)
616 return false;
617 return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
618}
619
henrik.lundin42dda502016-05-18 05:36:01 -0700620MixerParticipant::AudioFrameInfo Channel::GetAudioFrameWithMuted(
621 int32_t id,
622 AudioFrame* audioFrame) {
ivoc14d5dbe2016-07-04 07:06:55 -0700623 unsigned int ssrc;
nisse7d59f6b2017-02-21 03:40:24 -0800624 RTC_CHECK_EQ(GetRemoteSSRC(ssrc), 0);
ivoc14d5dbe2016-07-04 07:06:55 -0700625 event_log_proxy_->LogAudioPlayout(ssrc);
kwiberg55b97fe2016-01-28 05:22:45 -0800626 // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
henrik.lundind4ccb002016-05-17 12:21:55 -0700627 bool muted;
628 if (audio_coding_->PlayoutData10Ms(audioFrame->sample_rate_hz_, audioFrame,
629 &muted) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -0800630 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
631 "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
632 // In all likelihood, the audio in this frame is garbage. We return an
633 // error so that the audio mixer module doesn't add it to the mix. As
634 // a result, it won't be played out and the actions skipped here are
635 // irrelevant.
henrik.lundin42dda502016-05-18 05:36:01 -0700636 return MixerParticipant::AudioFrameInfo::kError;
kwiberg55b97fe2016-01-28 05:22:45 -0800637 }
henrik.lundina89ab962016-05-18 08:52:45 -0700638
639 if (muted) {
640 // TODO(henrik.lundin): We should be able to do better than this. But we
641 // will have to go through all the cases below where the audio samples may
642 // be used, and handle the muted case in some way.
aleloi6321b492016-12-05 01:46:09 -0800643 AudioFrameOperations::Mute(audioFrame);
henrik.lundina89ab962016-05-18 08:52:45 -0700644 }
kwiberg55b97fe2016-01-28 05:22:45 -0800645
kwiberg55b97fe2016-01-28 05:22:45 -0800646 // Convert module ID to internal VoE channel ID
647 audioFrame->id_ = VoEChannelId(audioFrame->id_);
648 // Store speech type for dead-or-alive detection
649 _outputSpeechType = audioFrame->speech_type_;
650
651 ChannelState::State state = channel_state_.Get();
652
kwiberg55b97fe2016-01-28 05:22:45 -0800653 {
654 // Pass the audio buffers to an optional sink callback, before applying
655 // scaling/panning, as that applies to the mix operation.
656 // External recipients of the audio (e.g. via AudioTrack), will do their
657 // own mixing/dynamic processing.
658 rtc::CritScope cs(&_callbackCritSect);
659 if (audio_sink_) {
660 AudioSinkInterface::Data data(
661 &audioFrame->data_[0], audioFrame->samples_per_channel_,
662 audioFrame->sample_rate_hz_, audioFrame->num_channels_,
663 audioFrame->timestamp_);
664 audio_sink_->OnData(data);
665 }
666 }
667
668 float output_gain = 1.0f;
669 float left_pan = 1.0f;
670 float right_pan = 1.0f;
671 {
672 rtc::CritScope cs(&volume_settings_critsect_);
673 output_gain = _outputGain;
674 left_pan = _panLeft;
675 right_pan = _panRight;
676 }
677
678 // Output volume scaling
679 if (output_gain < 0.99f || output_gain > 1.01f) {
680 AudioFrameOperations::ScaleWithSat(output_gain, *audioFrame);
681 }
682
683 // Scale left and/or right channel(s) if stereo and master balance is
684 // active
685
686 if (left_pan != 1.0f || right_pan != 1.0f) {
687 if (audioFrame->num_channels_ == 1) {
688 // Emulate stereo mode since panning is active.
689 // The mono signal is copied to both left and right channels here.
690 AudioFrameOperations::MonoToStereo(audioFrame);
691 }
692 // For true stereo mode (when we are receiving a stereo signal), no
693 // action is needed.
694
695 // Do the panning operation (the audio frame contains stereo at this
696 // stage)
697 AudioFrameOperations::Scale(left_pan, right_pan, *audioFrame);
698 }
699
700 // Mix decoded PCM output with file if file mixing is enabled
701 if (state.output_file_playing) {
702 MixAudioWithFile(*audioFrame, audioFrame->sample_rate_hz_);
henrik.lundina89ab962016-05-18 08:52:45 -0700703 muted = false; // We may have added non-zero samples.
kwiberg55b97fe2016-01-28 05:22:45 -0800704 }
705
kwiberg55b97fe2016-01-28 05:22:45 -0800706 // Record playout if enabled
707 {
708 rtc::CritScope cs(&_fileCritSect);
709
kwiberg5a25d952016-08-17 07:31:12 -0700710 if (_outputFileRecording && output_file_recorder_) {
711 output_file_recorder_->RecordAudioToFile(*audioFrame);
kwiberg55b97fe2016-01-28 05:22:45 -0800712 }
713 }
714
715 // Measure audio level (0-9)
henrik.lundina89ab962016-05-18 08:52:45 -0700716 // TODO(henrik.lundin) Use the |muted| information here too.
kwiberg55b97fe2016-01-28 05:22:45 -0800717 _outputAudioLevel.ComputeLevel(*audioFrame);
718
719 if (capture_start_rtp_time_stamp_ < 0 && audioFrame->timestamp_ != 0) {
720 // The first frame with a valid rtp timestamp.
721 capture_start_rtp_time_stamp_ = audioFrame->timestamp_;
722 }
723
724 if (capture_start_rtp_time_stamp_ >= 0) {
725 // audioFrame.timestamp_ should be valid from now on.
726
727 // Compute elapsed time.
728 int64_t unwrap_timestamp =
729 rtp_ts_wraparound_handler_->Unwrap(audioFrame->timestamp_);
730 audioFrame->elapsed_time_ms_ =
731 (unwrap_timestamp - capture_start_rtp_time_stamp_) /
ossue280cde2016-10-12 11:04:10 -0700732 (GetRtpTimestampRateHz() / 1000);
kwiberg55b97fe2016-01-28 05:22:45 -0800733
niklase@google.com470e71d2011-07-07 08:21:25 +0000734 {
kwiberg55b97fe2016-01-28 05:22:45 -0800735 rtc::CritScope lock(&ts_stats_lock_);
736 // Compute ntp time.
737 audioFrame->ntp_time_ms_ =
738 ntp_estimator_.Estimate(audioFrame->timestamp_);
739 // |ntp_time_ms_| won't be valid until at least 2 RTCP SRs are received.
740 if (audioFrame->ntp_time_ms_ > 0) {
741 // Compute |capture_start_ntp_time_ms_| so that
742 // |capture_start_ntp_time_ms_| + |elapsed_time_ms_| == |ntp_time_ms_|
743 capture_start_ntp_time_ms_ =
744 audioFrame->ntp_time_ms_ - audioFrame->elapsed_time_ms_;
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000745 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000746 }
kwiberg55b97fe2016-01-28 05:22:45 -0800747 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000748
henrik.lundin42dda502016-05-18 05:36:01 -0700749 return muted ? MixerParticipant::AudioFrameInfo::kMuted
750 : MixerParticipant::AudioFrameInfo::kNormal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000751}
752
aleloi6c278492016-10-20 14:24:39 -0700753AudioMixer::Source::AudioFrameInfo Channel::GetAudioFrameWithInfo(
754 int sample_rate_hz,
755 AudioFrame* audio_frame) {
756 audio_frame->sample_rate_hz_ = sample_rate_hz;
aleloiaed581a2016-10-20 06:32:39 -0700757
aleloi6c278492016-10-20 14:24:39 -0700758 const auto frame_info = GetAudioFrameWithMuted(-1, audio_frame);
aleloiaed581a2016-10-20 06:32:39 -0700759
760 using FrameInfo = AudioMixer::Source::AudioFrameInfo;
761 FrameInfo new_audio_frame_info = FrameInfo::kError;
762 switch (frame_info) {
763 case MixerParticipant::AudioFrameInfo::kNormal:
764 new_audio_frame_info = FrameInfo::kNormal;
765 break;
766 case MixerParticipant::AudioFrameInfo::kMuted:
767 new_audio_frame_info = FrameInfo::kMuted;
768 break;
769 case MixerParticipant::AudioFrameInfo::kError:
770 new_audio_frame_info = FrameInfo::kError;
771 break;
772 }
aleloi6c278492016-10-20 14:24:39 -0700773 return new_audio_frame_info;
aleloiaed581a2016-10-20 06:32:39 -0700774}
775
kwiberg55b97fe2016-01-28 05:22:45 -0800776int32_t Channel::NeededFrequency(int32_t id) const {
777 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
778 "Channel::NeededFrequency(id=%d)", id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000779
kwiberg55b97fe2016-01-28 05:22:45 -0800780 int highestNeeded = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000781
kwiberg55b97fe2016-01-28 05:22:45 -0800782 // Determine highest needed receive frequency
783 int32_t receiveFrequency = audio_coding_->ReceiveFrequency();
niklase@google.com470e71d2011-07-07 08:21:25 +0000784
kwiberg55b97fe2016-01-28 05:22:45 -0800785 // Return the bigger of playout and receive frequency in the ACM.
786 if (audio_coding_->PlayoutFrequency() > receiveFrequency) {
787 highestNeeded = audio_coding_->PlayoutFrequency();
788 } else {
789 highestNeeded = receiveFrequency;
790 }
791
792 // Special case, if we're playing a file on the playout side
793 // we take that frequency into consideration as well
794 // This is not needed on sending side, since the codec will
795 // limit the spectrum anyway.
796 if (channel_state_.Get().output_file_playing) {
797 rtc::CritScope cs(&_fileCritSect);
kwiberg5a25d952016-08-17 07:31:12 -0700798 if (output_file_player_) {
799 if (output_file_player_->Frequency() > highestNeeded) {
800 highestNeeded = output_file_player_->Frequency();
kwiberg55b97fe2016-01-28 05:22:45 -0800801 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000802 }
kwiberg55b97fe2016-01-28 05:22:45 -0800803 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000804
kwiberg55b97fe2016-01-28 05:22:45 -0800805 return (highestNeeded);
niklase@google.com470e71d2011-07-07 08:21:25 +0000806}
807
ossu5f7cfa52016-05-30 08:11:28 -0700808int32_t Channel::CreateChannel(
809 Channel*& channel,
810 int32_t channelId,
811 uint32_t instanceId,
solenberg88499ec2016-09-07 07:34:41 -0700812 const VoEBase::ChannelConfig& config) {
kwiberg55b97fe2016-01-28 05:22:45 -0800813 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId, channelId),
814 "Channel::CreateChannel(channelId=%d, instanceId=%d)", channelId,
815 instanceId);
niklase@google.com470e71d2011-07-07 08:21:25 +0000816
solenberg88499ec2016-09-07 07:34:41 -0700817 channel = new Channel(channelId, instanceId, config);
kwiberg55b97fe2016-01-28 05:22:45 -0800818 if (channel == NULL) {
819 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId, channelId),
820 "Channel::CreateChannel() unable to allocate memory for"
821 " channel");
822 return -1;
823 }
824 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000825}
826
kwiberg55b97fe2016-01-28 05:22:45 -0800827void Channel::PlayNotification(int32_t id, uint32_t durationMs) {
828 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
829 "Channel::PlayNotification(id=%d, durationMs=%d)", id,
830 durationMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000831
kwiberg55b97fe2016-01-28 05:22:45 -0800832 // Not implement yet
niklase@google.com470e71d2011-07-07 08:21:25 +0000833}
834
kwiberg55b97fe2016-01-28 05:22:45 -0800835void Channel::RecordNotification(int32_t id, uint32_t durationMs) {
836 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
837 "Channel::RecordNotification(id=%d, durationMs=%d)", id,
838 durationMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000839
kwiberg55b97fe2016-01-28 05:22:45 -0800840 // Not implement yet
niklase@google.com470e71d2011-07-07 08:21:25 +0000841}
842
kwiberg55b97fe2016-01-28 05:22:45 -0800843void Channel::PlayFileEnded(int32_t id) {
844 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
845 "Channel::PlayFileEnded(id=%d)", id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000846
kwiberg55b97fe2016-01-28 05:22:45 -0800847 if (id == _inputFilePlayerId) {
848 channel_state_.SetInputFilePlaying(false);
849 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
850 "Channel::PlayFileEnded() => input file player module is"
niklase@google.com470e71d2011-07-07 08:21:25 +0000851 " shutdown");
kwiberg55b97fe2016-01-28 05:22:45 -0800852 } else if (id == _outputFilePlayerId) {
853 channel_state_.SetOutputFilePlaying(false);
854 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
855 "Channel::PlayFileEnded() => output file player module is"
856 " shutdown");
857 }
858}
859
860void Channel::RecordFileEnded(int32_t id) {
861 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
862 "Channel::RecordFileEnded(id=%d)", id);
863
864 assert(id == _outputFileRecorderId);
865
866 rtc::CritScope cs(&_fileCritSect);
867
868 _outputFileRecording = false;
869 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
870 "Channel::RecordFileEnded() => output file recorder module is"
871 " shutdown");
niklase@google.com470e71d2011-07-07 08:21:25 +0000872}
873
pbos@webrtc.org92135212013-05-14 08:31:39 +0000874Channel::Channel(int32_t channelId,
minyue@webrtc.orge509f942013-09-12 17:03:00 +0000875 uint32_t instanceId,
solenberg88499ec2016-09-07 07:34:41 -0700876 const VoEBase::ChannelConfig& config)
tommi31fc21f2016-01-21 10:37:37 -0800877 : _instanceId(instanceId),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100878 _channelId(channelId),
ivoc14d5dbe2016-07-04 07:06:55 -0700879 event_log_proxy_(new RtcEventLogProxy()),
michaelt9332b7d2016-11-30 07:51:13 -0800880 rtcp_rtt_stats_proxy_(new RtcpRttStatsProxy()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100881 rtp_header_parser_(RtpHeaderParser::Create()),
magjedf3feeff2016-11-25 06:40:25 -0800882 rtp_payload_registry_(new RTPPayloadRegistry()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100883 rtp_receive_statistics_(
884 ReceiveStatistics::Create(Clock::GetRealTimeClock())),
885 rtp_receiver_(
886 RtpReceiver::CreateAudioReceiver(Clock::GetRealTimeClock(),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100887 this,
888 this,
889 rtp_payload_registry_.get())),
danilchap799a9d02016-09-22 03:36:27 -0700890 telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100891 _outputAudioLevel(),
892 _externalTransport(false),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100893 // Avoid conflict with other channels by adding 1024 - 1026,
894 // won't use as much as 1024 channels.
895 _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
896 _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
897 _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
898 _outputFileRecording(false),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100899 _timeStamp(0), // This is just an offset, RTP module will add it's own
900 // random offset
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100901 ntp_estimator_(Clock::GetRealTimeClock()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100902 playout_timestamp_rtp_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100903 playout_delay_ms_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100904 send_sequence_number_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100905 rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()),
906 capture_start_rtp_time_stamp_(-1),
907 capture_start_ntp_time_ms_(-1),
908 _engineStatisticsPtr(NULL),
909 _outputMixerPtr(NULL),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100910 _moduleProcessThreadPtr(NULL),
911 _audioDeviceModulePtr(NULL),
912 _voiceEngineObserverPtr(NULL),
913 _callbackCritSectPtr(NULL),
914 _transportPtr(NULL),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100915 _sendFrameType(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100916 _mixFileWithMicrophone(false),
solenberg1c2af8e2016-03-24 10:36:00 -0700917 input_mute_(false),
918 previous_frame_muted_(false),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100919 _panLeft(1.0f),
920 _panRight(1.0f),
921 _outputGain(1.0f),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100922 _lastLocalTimeStamp(0),
923 _lastPayloadType(0),
924 _includeAudioLevelIndication(false),
nisse284542b2017-01-10 08:58:32 -0800925 transport_overhead_per_packet_(0),
926 rtp_overhead_per_packet_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100927 _outputSpeechType(AudioFrame::kNormalSpeech),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100928 restored_packet_in_use_(false),
929 rtcp_observer_(new VoERtcpObserver(this)),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100930 associate_send_channel_(ChannelOwner(nullptr)),
solenberg88499ec2016-09-07 07:34:41 -0700931 pacing_enabled_(config.enable_voice_pacing),
stefanbba9dec2016-02-01 04:39:55 -0800932 feedback_observer_proxy_(new TransportFeedbackProxy()),
933 seq_num_allocator_proxy_(new TransportSequenceNumberProxy()),
ossu29b1a8d2016-06-13 07:34:51 -0700934 rtp_packet_sender_proxy_(new RtpPacketSenderProxy()),
Erik Språng737336d2016-07-29 12:59:36 +0200935 retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(),
936 kMaxRetransmissionWindowMs)),
michaelt566d8202017-01-12 10:17:38 -0800937 decoder_factory_(config.acm_config.decoder_factory) {
kwiberg55b97fe2016-01-28 05:22:45 -0800938 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, _channelId),
939 "Channel::Channel() - ctor");
solenberg88499ec2016-09-07 07:34:41 -0700940 AudioCodingModule::Config acm_config(config.acm_config);
kwiberg55b97fe2016-01-28 05:22:45 -0800941 acm_config.id = VoEModuleId(instanceId, channelId);
henrik.lundina89ab962016-05-18 08:52:45 -0700942 acm_config.neteq_config.enable_muted_state = true;
kwiberg55b97fe2016-01-28 05:22:45 -0800943 audio_coding_.reset(AudioCodingModule::Create(acm_config));
Henrik Lundin64dad832015-05-11 12:44:23 +0200944
kwiberg55b97fe2016-01-28 05:22:45 -0800945 _outputAudioLevel.Clear();
niklase@google.com470e71d2011-07-07 08:21:25 +0000946
kwiberg55b97fe2016-01-28 05:22:45 -0800947 RtpRtcp::Configuration configuration;
948 configuration.audio = true;
949 configuration.outgoing_transport = this;
michaeltbf65be52016-12-15 06:24:49 -0800950 configuration.overhead_observer = this;
kwiberg55b97fe2016-01-28 05:22:45 -0800951 configuration.receive_statistics = rtp_receive_statistics_.get();
952 configuration.bandwidth_callback = rtcp_observer_.get();
stefanbba9dec2016-02-01 04:39:55 -0800953 if (pacing_enabled_) {
954 configuration.paced_sender = rtp_packet_sender_proxy_.get();
955 configuration.transport_sequence_number_allocator =
956 seq_num_allocator_proxy_.get();
957 configuration.transport_feedback_callback = feedback_observer_proxy_.get();
958 }
ivoc14d5dbe2016-07-04 07:06:55 -0700959 configuration.event_log = &(*event_log_proxy_);
michaelt9332b7d2016-11-30 07:51:13 -0800960 configuration.rtt_stats = &(*rtcp_rtt_stats_proxy_);
Erik Språng737336d2016-07-29 12:59:36 +0200961 configuration.retransmission_rate_limiter =
962 retransmission_rate_limiter_.get();
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000963
kwiberg55b97fe2016-01-28 05:22:45 -0800964 _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
Peter Boström3dd5d1d2016-02-25 16:56:48 +0100965 _rtpRtcpModule->SetSendingMediaStatus(false);
niklase@google.com470e71d2011-07-07 08:21:25 +0000966}
967
kwiberg55b97fe2016-01-28 05:22:45 -0800968Channel::~Channel() {
969 rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL);
970 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, _channelId),
971 "Channel::~Channel() - dtor");
niklase@google.com470e71d2011-07-07 08:21:25 +0000972
kwiberg55b97fe2016-01-28 05:22:45 -0800973 StopSend();
974 StopPlayout();
niklase@google.com470e71d2011-07-07 08:21:25 +0000975
kwiberg55b97fe2016-01-28 05:22:45 -0800976 {
977 rtc::CritScope cs(&_fileCritSect);
kwiberg5a25d952016-08-17 07:31:12 -0700978 if (input_file_player_) {
979 input_file_player_->RegisterModuleFileCallback(NULL);
980 input_file_player_->StopPlayingFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000981 }
kwiberg5a25d952016-08-17 07:31:12 -0700982 if (output_file_player_) {
983 output_file_player_->RegisterModuleFileCallback(NULL);
984 output_file_player_->StopPlayingFile();
kwiberg55b97fe2016-01-28 05:22:45 -0800985 }
kwiberg5a25d952016-08-17 07:31:12 -0700986 if (output_file_recorder_) {
987 output_file_recorder_->RegisterModuleFileCallback(NULL);
988 output_file_recorder_->StopRecording();
kwiberg55b97fe2016-01-28 05:22:45 -0800989 }
990 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000991
kwiberg55b97fe2016-01-28 05:22:45 -0800992 // The order to safely shutdown modules in a channel is:
993 // 1. De-register callbacks in modules
994 // 2. De-register modules in process thread
995 // 3. Destroy modules
996 if (audio_coding_->RegisterTransportCallback(NULL) == -1) {
997 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
998 "~Channel() failed to de-register transport callback"
999 " (Audio coding module)");
1000 }
1001 if (audio_coding_->RegisterVADCallback(NULL) == -1) {
1002 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1003 "~Channel() failed to de-register VAD callback"
1004 " (Audio coding module)");
1005 }
1006 // De-register modules in process thread
1007 _moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get());
tommi@webrtc.org3985f012015-02-27 13:36:34 +00001008
kwiberg55b97fe2016-01-28 05:22:45 -08001009 // End of modules shutdown
niklase@google.com470e71d2011-07-07 08:21:25 +00001010}
1011
kwiberg55b97fe2016-01-28 05:22:45 -08001012int32_t Channel::Init() {
1013 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1014 "Channel::Init()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001015
kwiberg55b97fe2016-01-28 05:22:45 -08001016 channel_state_.Reset();
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +00001017
kwiberg55b97fe2016-01-28 05:22:45 -08001018 // --- Initial sanity
niklase@google.com470e71d2011-07-07 08:21:25 +00001019
kwiberg55b97fe2016-01-28 05:22:45 -08001020 if ((_engineStatisticsPtr == NULL) || (_moduleProcessThreadPtr == NULL)) {
1021 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
1022 "Channel::Init() must call SetEngineInformation() first");
1023 return -1;
1024 }
1025
1026 // --- Add modules to process thread (for periodic schedulation)
1027
1028 _moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get());
1029
1030 // --- ACM initialization
1031
1032 if (audio_coding_->InitializeReceiver() == -1) {
1033 _engineStatisticsPtr->SetLastError(
1034 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1035 "Channel::Init() unable to initialize the ACM - 1");
1036 return -1;
1037 }
1038
1039 // --- RTP/RTCP module initialization
1040
1041 // Ensure that RTCP is enabled by default for the created channel.
1042 // Note that, the module will keep generating RTCP until it is explicitly
1043 // disabled by the user.
1044 // After StopListen (when no sockets exists), RTCP packets will no longer
1045 // be transmitted since the Transport object will then be invalid.
danilchap799a9d02016-09-22 03:36:27 -07001046 telephone_event_handler_->SetTelephoneEventForwardToDecoder(true);
kwiberg55b97fe2016-01-28 05:22:45 -08001047 // RTCP is enabled by default.
1048 _rtpRtcpModule->SetRTCPStatus(RtcpMode::kCompound);
1049 // --- Register all permanent callbacks
1050 const bool fail = (audio_coding_->RegisterTransportCallback(this) == -1) ||
1051 (audio_coding_->RegisterVADCallback(this) == -1);
1052
1053 if (fail) {
1054 _engineStatisticsPtr->SetLastError(
1055 VE_CANNOT_INIT_CHANNEL, kTraceError,
1056 "Channel::Init() callbacks not registered");
1057 return -1;
1058 }
1059
1060 // --- Register all supported codecs to the receiving side of the
1061 // RTP/RTCP module
1062
1063 CodecInst codec;
1064 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
1065
1066 for (int idx = 0; idx < nSupportedCodecs; idx++) {
1067 // Open up the RTP/RTCP receiver for all supported codecs
1068 if ((audio_coding_->Codec(idx, &codec) == -1) ||
magjed56124bd2016-11-24 09:34:46 -08001069 (rtp_receiver_->RegisterReceivePayload(codec) == -1)) {
kwiberg55b97fe2016-01-28 05:22:45 -08001070 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1071 "Channel::Init() unable to register %s "
1072 "(%d/%d/%" PRIuS "/%d) to RTP/RTCP receiver",
1073 codec.plname, codec.pltype, codec.plfreq, codec.channels,
1074 codec.rate);
1075 } else {
1076 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1077 "Channel::Init() %s (%d/%d/%" PRIuS
1078 "/%d) has been "
1079 "added to the RTP/RTCP receiver",
1080 codec.plname, codec.pltype, codec.plfreq, codec.channels,
1081 codec.rate);
niklase@google.com470e71d2011-07-07 08:21:25 +00001082 }
1083
kwiberg55b97fe2016-01-28 05:22:45 -08001084 // Ensure that PCMU is used as default codec on the sending side
1085 if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1)) {
1086 SetSendCodec(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +00001087 }
1088
kwiberg55b97fe2016-01-28 05:22:45 -08001089 // Register default PT for outband 'telephone-event'
1090 if (!STR_CASE_CMP(codec.plname, "telephone-event")) {
kwibergc8d071e2016-04-06 12:22:38 -07001091 if (_rtpRtcpModule->RegisterSendPayload(codec) == -1 ||
kwibergda2bf4e2016-10-24 13:47:09 -07001092 !audio_coding_->RegisterReceiveCodec(codec.pltype,
1093 CodecInstToSdp(codec))) {
kwiberg55b97fe2016-01-28 05:22:45 -08001094 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1095 "Channel::Init() failed to register outband "
1096 "'telephone-event' (%d/%d) correctly",
1097 codec.pltype, codec.plfreq);
1098 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001099 }
1100
kwiberg55b97fe2016-01-28 05:22:45 -08001101 if (!STR_CASE_CMP(codec.plname, "CN")) {
kwibergc8d071e2016-04-06 12:22:38 -07001102 if (!codec_manager_.RegisterEncoder(codec) ||
1103 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get()) ||
kwibergda2bf4e2016-10-24 13:47:09 -07001104 !audio_coding_->RegisterReceiveCodec(codec.pltype,
1105 CodecInstToSdp(codec)) ||
kwibergc8d071e2016-04-06 12:22:38 -07001106 _rtpRtcpModule->RegisterSendPayload(codec) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08001107 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1108 "Channel::Init() failed to register CN (%d/%d) "
1109 "correctly - 1",
1110 codec.pltype, codec.plfreq);
1111 }
1112 }
kwiberg55b97fe2016-01-28 05:22:45 -08001113 }
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001114
kwiberg55b97fe2016-01-28 05:22:45 -08001115 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001116}
1117
kwiberg55b97fe2016-01-28 05:22:45 -08001118int32_t Channel::SetEngineInformation(Statistics& engineStatistics,
1119 OutputMixer& outputMixer,
kwiberg55b97fe2016-01-28 05:22:45 -08001120 ProcessThread& moduleProcessThread,
1121 AudioDeviceModule& audioDeviceModule,
1122 VoiceEngineObserver* voiceEngineObserver,
1123 rtc::CriticalSection* callbackCritSect) {
1124 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1125 "Channel::SetEngineInformation()");
1126 _engineStatisticsPtr = &engineStatistics;
1127 _outputMixerPtr = &outputMixer;
kwiberg55b97fe2016-01-28 05:22:45 -08001128 _moduleProcessThreadPtr = &moduleProcessThread;
1129 _audioDeviceModulePtr = &audioDeviceModule;
1130 _voiceEngineObserverPtr = voiceEngineObserver;
1131 _callbackCritSectPtr = callbackCritSect;
1132 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001133}
1134
kwiberg55b97fe2016-01-28 05:22:45 -08001135int32_t Channel::UpdateLocalTimeStamp() {
1136 _timeStamp += static_cast<uint32_t>(_audioFrame.samples_per_channel_);
1137 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001138}
1139
kwibergb7f89d62016-02-17 10:04:18 -08001140void Channel::SetSink(std::unique_ptr<AudioSinkInterface> sink) {
tommi31fc21f2016-01-21 10:37:37 -08001141 rtc::CritScope cs(&_callbackCritSect);
deadbeef2d110be2016-01-13 12:00:26 -08001142 audio_sink_ = std::move(sink);
Tommif888bb52015-12-12 01:37:01 +01001143}
1144
ossu29b1a8d2016-06-13 07:34:51 -07001145const rtc::scoped_refptr<AudioDecoderFactory>&
1146Channel::GetAudioDecoderFactory() const {
1147 return decoder_factory_;
1148}
1149
kwiberg55b97fe2016-01-28 05:22:45 -08001150int32_t Channel::StartPlayout() {
1151 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1152 "Channel::StartPlayout()");
1153 if (channel_state_.Get().playing) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001154 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001155 }
1156
solenberge374e012017-02-14 04:55:00 -08001157 // Add participant as candidates for mixing.
1158 if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0) {
1159 _engineStatisticsPtr->SetLastError(
1160 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1161 "StartPlayout() failed to add participant to mixer");
1162 return -1;
kwiberg55b97fe2016-01-28 05:22:45 -08001163 }
1164
1165 channel_state_.SetPlaying(true);
1166 if (RegisterFilePlayingToMixer() != 0)
1167 return -1;
1168
1169 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001170}
1171
kwiberg55b97fe2016-01-28 05:22:45 -08001172int32_t Channel::StopPlayout() {
1173 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1174 "Channel::StopPlayout()");
1175 if (!channel_state_.Get().playing) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001176 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001177 }
1178
solenberge374e012017-02-14 04:55:00 -08001179 // Remove participant as candidates for mixing
1180 if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0) {
1181 _engineStatisticsPtr->SetLastError(
1182 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1183 "StopPlayout() failed to remove participant from mixer");
1184 return -1;
kwiberg55b97fe2016-01-28 05:22:45 -08001185 }
1186
1187 channel_state_.SetPlaying(false);
1188 _outputAudioLevel.Clear();
1189
1190 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001191}
1192
kwiberg55b97fe2016-01-28 05:22:45 -08001193int32_t Channel::StartSend() {
1194 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1195 "Channel::StartSend()");
kwiberg55b97fe2016-01-28 05:22:45 -08001196 if (channel_state_.Get().sending) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001197 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001198 }
1199 channel_state_.SetSending(true);
niklase@google.com470e71d2011-07-07 08:21:25 +00001200
solenberg08b19df2017-02-15 00:42:31 -08001201 // Resume the previous sequence number which was reset by StopSend(). This
1202 // needs to be done before |sending| is set to true on the RTP/RTCP module.
1203 if (send_sequence_number_) {
1204 _rtpRtcpModule->SetSequenceNumber(send_sequence_number_);
1205 }
Peter Boström3dd5d1d2016-02-25 16:56:48 +01001206 _rtpRtcpModule->SetSendingMediaStatus(true);
kwiberg55b97fe2016-01-28 05:22:45 -08001207 if (_rtpRtcpModule->SetSendingStatus(true) != 0) {
1208 _engineStatisticsPtr->SetLastError(
1209 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1210 "StartSend() RTP/RTCP failed to start sending");
Peter Boström3dd5d1d2016-02-25 16:56:48 +01001211 _rtpRtcpModule->SetSendingMediaStatus(false);
kwiberg55b97fe2016-01-28 05:22:45 -08001212 rtc::CritScope cs(&_callbackCritSect);
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +00001213 channel_state_.SetSending(false);
kwiberg55b97fe2016-01-28 05:22:45 -08001214 return -1;
1215 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001216
kwiberg55b97fe2016-01-28 05:22:45 -08001217 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001218}
1219
kwiberg55b97fe2016-01-28 05:22:45 -08001220int32_t Channel::StopSend() {
1221 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1222 "Channel::StopSend()");
1223 if (!channel_state_.Get().sending) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001224 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001225 }
1226 channel_state_.SetSending(false);
1227
1228 // Store the sequence number to be able to pick up the same sequence for
1229 // the next StartSend(). This is needed for restarting device, otherwise
1230 // it might cause libSRTP to complain about packets being replayed.
1231 // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring
1232 // CL is landed. See issue
1233 // https://code.google.com/p/webrtc/issues/detail?id=2111 .
1234 send_sequence_number_ = _rtpRtcpModule->SequenceNumber();
1235
1236 // Reset sending SSRC and sequence number and triggers direct transmission
1237 // of RTCP BYE
1238 if (_rtpRtcpModule->SetSendingStatus(false) == -1) {
1239 _engineStatisticsPtr->SetLastError(
1240 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1241 "StartSend() RTP/RTCP failed to stop sending");
1242 }
Peter Boström3dd5d1d2016-02-25 16:56:48 +01001243 _rtpRtcpModule->SetSendingMediaStatus(false);
kwiberg55b97fe2016-01-28 05:22:45 -08001244
1245 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001246}
1247
kwiberg55b97fe2016-01-28 05:22:45 -08001248int32_t Channel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer) {
1249 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1250 "Channel::RegisterVoiceEngineObserver()");
1251 rtc::CritScope cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001252
kwiberg55b97fe2016-01-28 05:22:45 -08001253 if (_voiceEngineObserverPtr) {
1254 _engineStatisticsPtr->SetLastError(
1255 VE_INVALID_OPERATION, kTraceError,
1256 "RegisterVoiceEngineObserver() observer already enabled");
1257 return -1;
1258 }
1259 _voiceEngineObserverPtr = &observer;
1260 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001261}
1262
kwiberg55b97fe2016-01-28 05:22:45 -08001263int32_t Channel::DeRegisterVoiceEngineObserver() {
1264 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1265 "Channel::DeRegisterVoiceEngineObserver()");
1266 rtc::CritScope cs(&_callbackCritSect);
1267
1268 if (!_voiceEngineObserverPtr) {
1269 _engineStatisticsPtr->SetLastError(
1270 VE_INVALID_OPERATION, kTraceWarning,
1271 "DeRegisterVoiceEngineObserver() observer already disabled");
1272 return 0;
1273 }
1274 _voiceEngineObserverPtr = NULL;
1275 return 0;
1276}
1277
1278int32_t Channel::GetSendCodec(CodecInst& codec) {
kwibergc8d071e2016-04-06 12:22:38 -07001279 auto send_codec = codec_manager_.GetCodecInst();
kwiberg1fd4a4a2015-11-03 11:20:50 -08001280 if (send_codec) {
1281 codec = *send_codec;
1282 return 0;
1283 }
1284 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001285}
1286
kwiberg55b97fe2016-01-28 05:22:45 -08001287int32_t Channel::GetRecCodec(CodecInst& codec) {
1288 return (audio_coding_->ReceiveCodec(&codec));
niklase@google.com470e71d2011-07-07 08:21:25 +00001289}
1290
kwiberg55b97fe2016-01-28 05:22:45 -08001291int32_t Channel::SetSendCodec(const CodecInst& codec) {
1292 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1293 "Channel::SetSendCodec()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001294
kwibergc8d071e2016-04-06 12:22:38 -07001295 if (!codec_manager_.RegisterEncoder(codec) ||
1296 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
kwiberg55b97fe2016-01-28 05:22:45 -08001297 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
1298 "SetSendCodec() failed to register codec to ACM");
1299 return -1;
1300 }
1301
1302 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1303 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1304 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1305 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
1306 "SetSendCodec() failed to register codec to"
1307 " RTP/RTCP module");
1308 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001309 }
kwiberg55b97fe2016-01-28 05:22:45 -08001310 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001311
kwiberg55b97fe2016-01-28 05:22:45 -08001312 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001313}
1314
minyue78b4d562016-11-30 04:47:39 -08001315void Channel::SetBitRate(int bitrate_bps, int64_t probing_interval_ms) {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001316 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1317 "Channel::SetBitRate(bitrate_bps=%d)", bitrate_bps);
minyue7e304322016-10-12 05:00:55 -07001318 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
michaelt2fedf9c2016-11-28 02:34:18 -08001319 if (*encoder) {
1320 (*encoder)->OnReceivedUplinkBandwidth(
michaelt566d8202017-01-12 10:17:38 -08001321 bitrate_bps, rtc::Optional<int64_t>(probing_interval_ms));
michaelt2fedf9c2016-11-28 02:34:18 -08001322 }
1323 });
michaelt566d8202017-01-12 10:17:38 -08001324 retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
Ivo Creusenadf89b72015-04-29 16:03:33 +02001325}
1326
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +00001327void Channel::OnIncomingFractionLoss(int fraction_lost) {
minyue7e304322016-10-12 05:00:55 -07001328 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1329 if (*encoder)
1330 (*encoder)->OnReceivedUplinkPacketLossFraction(fraction_lost / 255.0f);
1331 });
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00001332}
1333
kwiberg55b97fe2016-01-28 05:22:45 -08001334int32_t Channel::SetVADStatus(bool enableVAD,
1335 ACMVADMode mode,
1336 bool disableDTX) {
1337 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1338 "Channel::SetVADStatus(mode=%d)", mode);
kwibergc8d071e2016-04-06 12:22:38 -07001339 RTC_DCHECK(!(disableDTX && enableVAD)); // disableDTX mode is deprecated.
1340 if (!codec_manager_.SetVAD(enableVAD, mode) ||
1341 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
kwiberg55b97fe2016-01-28 05:22:45 -08001342 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR,
1343 kTraceError,
1344 "SetVADStatus() failed to set VAD");
1345 return -1;
1346 }
1347 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001348}
1349
kwiberg55b97fe2016-01-28 05:22:45 -08001350int32_t Channel::GetVADStatus(bool& enabledVAD,
1351 ACMVADMode& mode,
1352 bool& disabledDTX) {
kwibergc8d071e2016-04-06 12:22:38 -07001353 const auto* params = codec_manager_.GetStackParams();
1354 enabledVAD = params->use_cng;
1355 mode = params->vad_mode;
1356 disabledDTX = !params->use_cng;
kwiberg55b97fe2016-01-28 05:22:45 -08001357 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001358}
1359
kwiberg55b97fe2016-01-28 05:22:45 -08001360int32_t Channel::SetRecPayloadType(const CodecInst& codec) {
kwibergd32bf752017-01-19 07:03:59 -08001361 return SetRecPayloadType(codec.pltype, CodecInstToSdp(codec));
1362}
1363
1364int32_t Channel::SetRecPayloadType(int payload_type,
1365 const SdpAudioFormat& format) {
kwiberg55b97fe2016-01-28 05:22:45 -08001366 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1367 "Channel::SetRecPayloadType()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001368
kwiberg55b97fe2016-01-28 05:22:45 -08001369 if (channel_state_.Get().playing) {
1370 _engineStatisticsPtr->SetLastError(
1371 VE_ALREADY_PLAYING, kTraceError,
1372 "SetRecPayloadType() unable to set PT while playing");
1373 return -1;
1374 }
kwiberg55b97fe2016-01-28 05:22:45 -08001375
kwiberg09f090c2017-03-01 01:57:11 -08001376 const CodecInst codec = SdpToCodecInst(payload_type, format);
kwibergd32bf752017-01-19 07:03:59 -08001377
1378 if (payload_type == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08001379 // De-register the selected codec (RTP/RTCP module and ACM)
1380
1381 int8_t pltype(-1);
1382 CodecInst rxCodec = codec;
1383
1384 // Get payload type for the given codec
magjed56124bd2016-11-24 09:34:46 -08001385 rtp_payload_registry_->ReceivePayloadType(rxCodec, &pltype);
kwiberg55b97fe2016-01-28 05:22:45 -08001386 rxCodec.pltype = pltype;
1387
1388 if (rtp_receiver_->DeRegisterReceivePayload(pltype) != 0) {
1389 _engineStatisticsPtr->SetLastError(
1390 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1391 "SetRecPayloadType() RTP/RTCP-module deregistration "
1392 "failed");
1393 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001394 }
kwiberg55b97fe2016-01-28 05:22:45 -08001395 if (audio_coding_->UnregisterReceiveCodec(rxCodec.pltype) != 0) {
1396 _engineStatisticsPtr->SetLastError(
1397 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1398 "SetRecPayloadType() ACM deregistration failed - 1");
1399 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001400 }
kwiberg55b97fe2016-01-28 05:22:45 -08001401 return 0;
1402 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001403
magjed56124bd2016-11-24 09:34:46 -08001404 if (rtp_receiver_->RegisterReceivePayload(codec) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001405 // First attempt to register failed => de-register and try again
kwibergc8d071e2016-04-06 12:22:38 -07001406 // TODO(kwiberg): Retrying is probably not necessary, since
1407 // AcmReceiver::AddCodec also retries.
kwiberg55b97fe2016-01-28 05:22:45 -08001408 rtp_receiver_->DeRegisterReceivePayload(codec.pltype);
magjed56124bd2016-11-24 09:34:46 -08001409 if (rtp_receiver_->RegisterReceivePayload(codec) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001410 _engineStatisticsPtr->SetLastError(
1411 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1412 "SetRecPayloadType() RTP/RTCP-module registration failed");
1413 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001414 }
kwiberg55b97fe2016-01-28 05:22:45 -08001415 }
kwibergd32bf752017-01-19 07:03:59 -08001416 if (!audio_coding_->RegisterReceiveCodec(payload_type, format)) {
1417 audio_coding_->UnregisterReceiveCodec(payload_type);
1418 if (!audio_coding_->RegisterReceiveCodec(payload_type, format)) {
kwiberg55b97fe2016-01-28 05:22:45 -08001419 _engineStatisticsPtr->SetLastError(
1420 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1421 "SetRecPayloadType() ACM registration failed - 1");
1422 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001423 }
kwiberg55b97fe2016-01-28 05:22:45 -08001424 }
1425 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001426}
1427
kwiberg55b97fe2016-01-28 05:22:45 -08001428int32_t Channel::GetRecPayloadType(CodecInst& codec) {
1429 int8_t payloadType(-1);
magjed56124bd2016-11-24 09:34:46 -08001430 if (rtp_payload_registry_->ReceivePayloadType(codec, &payloadType) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001431 _engineStatisticsPtr->SetLastError(
1432 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1433 "GetRecPayloadType() failed to retrieve RX payload type");
1434 return -1;
1435 }
1436 codec.pltype = payloadType;
1437 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001438}
1439
kwiberg55b97fe2016-01-28 05:22:45 -08001440int32_t Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency) {
1441 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1442 "Channel::SetSendCNPayloadType()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001443
kwiberg55b97fe2016-01-28 05:22:45 -08001444 CodecInst codec;
1445 int32_t samplingFreqHz(-1);
1446 const size_t kMono = 1;
1447 if (frequency == kFreq32000Hz)
1448 samplingFreqHz = 32000;
1449 else if (frequency == kFreq16000Hz)
1450 samplingFreqHz = 16000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001451
kwiberg55b97fe2016-01-28 05:22:45 -08001452 if (audio_coding_->Codec("CN", &codec, samplingFreqHz, kMono) == -1) {
1453 _engineStatisticsPtr->SetLastError(
1454 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1455 "SetSendCNPayloadType() failed to retrieve default CN codec "
1456 "settings");
1457 return -1;
1458 }
1459
1460 // Modify the payload type (must be set to dynamic range)
1461 codec.pltype = type;
1462
kwibergc8d071e2016-04-06 12:22:38 -07001463 if (!codec_manager_.RegisterEncoder(codec) ||
1464 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
kwiberg55b97fe2016-01-28 05:22:45 -08001465 _engineStatisticsPtr->SetLastError(
1466 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1467 "SetSendCNPayloadType() failed to register CN to ACM");
1468 return -1;
1469 }
1470
1471 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1472 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1473 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1474 _engineStatisticsPtr->SetLastError(
1475 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1476 "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
1477 "module");
1478 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001479 }
kwiberg55b97fe2016-01-28 05:22:45 -08001480 }
1481 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001482}
1483
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001484int Channel::SetOpusMaxPlaybackRate(int frequency_hz) {
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001485 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001486 "Channel::SetOpusMaxPlaybackRate()");
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001487
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001488 if (audio_coding_->SetOpusMaxPlaybackRate(frequency_hz) != 0) {
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001489 _engineStatisticsPtr->SetLastError(
1490 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001491 "SetOpusMaxPlaybackRate() failed to set maximum playback rate");
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001492 return -1;
1493 }
1494 return 0;
1495}
1496
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +00001497int Channel::SetOpusDtx(bool enable_dtx) {
1498 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1499 "Channel::SetOpusDtx(%d)", enable_dtx);
Minyue Li092041c2015-05-11 12:19:35 +02001500 int ret = enable_dtx ? audio_coding_->EnableOpusDtx()
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +00001501 : audio_coding_->DisableOpusDtx();
1502 if (ret != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001503 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR,
1504 kTraceError, "SetOpusDtx() failed");
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +00001505 return -1;
1506 }
1507 return 0;
1508}
1509
ivoc85228d62016-07-27 04:53:47 -07001510int Channel::GetOpusDtx(bool* enabled) {
1511 int success = -1;
1512 audio_coding_->QueryEncoder([&](AudioEncoder const* encoder) {
1513 if (encoder) {
1514 *enabled = encoder->GetDtx();
1515 success = 0;
1516 }
1517 });
1518 return success;
1519}
1520
minyue7e304322016-10-12 05:00:55 -07001521bool Channel::EnableAudioNetworkAdaptor(const std::string& config_string) {
1522 bool success = false;
1523 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1524 if (*encoder) {
1525 success = (*encoder)->EnableAudioNetworkAdaptor(
michaeltbf279fc2017-01-13 06:02:29 -08001526 config_string, event_log_proxy_.get(), Clock::GetRealTimeClock());
minyue7e304322016-10-12 05:00:55 -07001527 }
1528 });
1529 return success;
1530}
1531
1532void Channel::DisableAudioNetworkAdaptor() {
1533 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1534 if (*encoder)
1535 (*encoder)->DisableAudioNetworkAdaptor();
1536 });
1537}
1538
1539void Channel::SetReceiverFrameLengthRange(int min_frame_length_ms,
1540 int max_frame_length_ms) {
1541 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1542 if (*encoder) {
1543 (*encoder)->SetReceiverFrameLengthRange(min_frame_length_ms,
1544 max_frame_length_ms);
1545 }
1546 });
1547}
1548
mflodman3d7db262016-04-29 00:57:13 -07001549int32_t Channel::RegisterExternalTransport(Transport* transport) {
kwiberg55b97fe2016-01-28 05:22:45 -08001550 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00001551 "Channel::RegisterExternalTransport()");
1552
kwiberg55b97fe2016-01-28 05:22:45 -08001553 rtc::CritScope cs(&_callbackCritSect);
kwiberg55b97fe2016-01-28 05:22:45 -08001554 if (_externalTransport) {
1555 _engineStatisticsPtr->SetLastError(
1556 VE_INVALID_OPERATION, kTraceError,
1557 "RegisterExternalTransport() external transport already enabled");
1558 return -1;
1559 }
1560 _externalTransport = true;
mflodman3d7db262016-04-29 00:57:13 -07001561 _transportPtr = transport;
kwiberg55b97fe2016-01-28 05:22:45 -08001562 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001563}
1564
kwiberg55b97fe2016-01-28 05:22:45 -08001565int32_t Channel::DeRegisterExternalTransport() {
1566 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1567 "Channel::DeRegisterExternalTransport()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001568
kwiberg55b97fe2016-01-28 05:22:45 -08001569 rtc::CritScope cs(&_callbackCritSect);
mflodman3d7db262016-04-29 00:57:13 -07001570 if (_transportPtr) {
1571 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1572 "DeRegisterExternalTransport() all transport is disabled");
1573 } else {
kwiberg55b97fe2016-01-28 05:22:45 -08001574 _engineStatisticsPtr->SetLastError(
1575 VE_INVALID_OPERATION, kTraceWarning,
1576 "DeRegisterExternalTransport() external transport already "
1577 "disabled");
kwiberg55b97fe2016-01-28 05:22:45 -08001578 }
1579 _externalTransport = false;
1580 _transportPtr = NULL;
kwiberg55b97fe2016-01-28 05:22:45 -08001581 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001582}
1583
nisse657bab22017-02-21 06:28:10 -08001584// TODO(nisse): Delete this method together with ReceivedRTPPacket.
1585// It's a temporary hack to support both ReceivedRTPPacket and
1586// OnRtpPacket interfaces without too much code duplication.
1587bool Channel::OnRtpPacketWithHeader(const uint8_t* received_packet,
1588 size_t length,
1589 RTPHeader *header) {
1590 // Store playout timestamp for the received RTP packet
1591 UpdatePlayoutTimestamp(false);
1592
1593 header->payload_type_frequency =
1594 rtp_payload_registry_->GetPayloadTypeFrequency(header->payloadType);
1595 if (header->payload_type_frequency < 0)
1596 return false;
1597 bool in_order = IsPacketInOrder(*header);
1598 rtp_receive_statistics_->IncomingPacket(
1599 *header, length, IsPacketRetransmitted(*header, in_order));
1600 rtp_payload_registry_->SetIncomingPayloadType(*header);
1601
1602 return ReceivePacket(received_packet, length, *header, in_order);
1603}
1604
mflodman3d7db262016-04-29 00:57:13 -07001605int32_t Channel::ReceivedRTPPacket(const uint8_t* received_packet,
kwiberg55b97fe2016-01-28 05:22:45 -08001606 size_t length,
solenberg@webrtc.orgb1f50102014-03-24 10:38:25 +00001607 const PacketTime& packet_time) {
kwiberg55b97fe2016-01-28 05:22:45 -08001608 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001609 "Channel::ReceivedRTPPacket()");
1610
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +00001611 RTPHeader header;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001612 if (!rtp_header_parser_->Parse(received_packet, length, &header)) {
1613 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1614 "Incoming packet: invalid RTP header");
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +00001615 return -1;
1616 }
nisse657bab22017-02-21 06:28:10 -08001617 return OnRtpPacketWithHeader(received_packet, length, &header) ? 0 : -1;
1618}
solenberg@webrtc.orgb1f50102014-03-24 10:38:25 +00001619
nisse657bab22017-02-21 06:28:10 -08001620void Channel::OnRtpPacket(const RtpPacketReceived& packet) {
1621 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
1622 "Channel::ReceivedRTPPacket()");
1623
1624 RTPHeader header;
1625 packet.GetHeader(&header);
1626 OnRtpPacketWithHeader(packet.data(), packet.size(), &header);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001627}
1628
1629bool Channel::ReceivePacket(const uint8_t* packet,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001630 size_t packet_length,
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001631 const RTPHeader& header,
1632 bool in_order) {
minyue@webrtc.org456f0142015-01-23 11:58:42 +00001633 if (rtp_payload_registry_->IsRtx(header)) {
1634 return HandleRtxPacket(packet, packet_length, header);
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001635 }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001636 const uint8_t* payload = packet + header.headerLength;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001637 assert(packet_length >= header.headerLength);
1638 size_t payload_length = packet_length - header.headerLength;
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001639 PayloadUnion payload_specific;
1640 if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001641 &payload_specific)) {
1642 return false;
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001643 }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001644 return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
1645 payload_specific, in_order);
1646}
1647
minyue@webrtc.org456f0142015-01-23 11:58:42 +00001648bool Channel::HandleRtxPacket(const uint8_t* packet,
1649 size_t packet_length,
1650 const RTPHeader& header) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001651 if (!rtp_payload_registry_->IsRtx(header))
1652 return false;
1653
1654 // Remove the RTX header and parse the original RTP header.
1655 if (packet_length < header.headerLength)
1656 return false;
1657 if (packet_length > kVoiceEngineMaxIpPacketSizeBytes)
1658 return false;
1659 if (restored_packet_in_use_) {
1660 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1661 "Multiple RTX headers detected, dropping packet");
1662 return false;
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001663 }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001664 if (!rtp_payload_registry_->RestoreOriginalPacket(
noahric65220a72015-10-14 11:29:49 -07001665 restored_packet_, packet, &packet_length, rtp_receiver_->SSRC(),
1666 header)) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001667 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1668 "Incoming RTX packet: invalid RTP header");
1669 return false;
1670 }
1671 restored_packet_in_use_ = true;
noahric65220a72015-10-14 11:29:49 -07001672 bool ret = OnRecoveredPacket(restored_packet_, packet_length);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001673 restored_packet_in_use_ = false;
1674 return ret;
1675}
1676
1677bool Channel::IsPacketInOrder(const RTPHeader& header) const {
1678 StreamStatistician* statistician =
1679 rtp_receive_statistics_->GetStatistician(header.ssrc);
1680 if (!statistician)
1681 return false;
1682 return statistician->IsPacketInOrder(header.sequenceNumber);
niklase@google.com470e71d2011-07-07 08:21:25 +00001683}
1684
stefan@webrtc.org48df3812013-11-08 15:18:52 +00001685bool Channel::IsPacketRetransmitted(const RTPHeader& header,
1686 bool in_order) const {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001687 // Retransmissions are handled separately if RTX is enabled.
1688 if (rtp_payload_registry_->RtxEnabled())
1689 return false;
1690 StreamStatistician* statistician =
1691 rtp_receive_statistics_->GetStatistician(header.ssrc);
1692 if (!statistician)
1693 return false;
1694 // Check if this is a retransmission.
pkasting@chromium.org16825b12015-01-12 21:51:21 +00001695 int64_t min_rtt = 0;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001696 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
kwiberg55b97fe2016-01-28 05:22:45 -08001697 return !in_order && statistician->IsRetransmitOfOldPacket(header, min_rtt);
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001698}
1699
mflodman3d7db262016-04-29 00:57:13 -07001700int32_t Channel::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
kwiberg55b97fe2016-01-28 05:22:45 -08001701 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001702 "Channel::ReceivedRTCPPacket()");
1703 // Store playout timestamp for the received RTCP packet
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00001704 UpdatePlayoutTimestamp(true);
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001705
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001706 // Deliver RTCP packet to RTP/RTCP module for parsing
mflodman3d7db262016-04-29 00:57:13 -07001707 if (_rtpRtcpModule->IncomingRtcpPacket(data, length) == -1) {
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001708 _engineStatisticsPtr->SetLastError(
1709 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
1710 "Channel::IncomingRTPPacket() RTCP packet is invalid");
1711 }
wu@webrtc.org82c4b852014-05-20 22:55:01 +00001712
Minyue2013aec2015-05-13 14:14:42 +02001713 int64_t rtt = GetRTT(true);
1714 if (rtt == 0) {
1715 // Waiting for valid RTT.
1716 return 0;
1717 }
Erik Språng737336d2016-07-29 12:59:36 +02001718
1719 int64_t nack_window_ms = rtt;
1720 if (nack_window_ms < kMinRetransmissionWindowMs) {
1721 nack_window_ms = kMinRetransmissionWindowMs;
1722 } else if (nack_window_ms > kMaxRetransmissionWindowMs) {
1723 nack_window_ms = kMaxRetransmissionWindowMs;
1724 }
1725 retransmission_rate_limiter_->SetWindowSize(nack_window_ms);
1726
minyue7e304322016-10-12 05:00:55 -07001727 // Invoke audio encoders OnReceivedRtt().
1728 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1729 if (*encoder)
1730 (*encoder)->OnReceivedRtt(rtt);
1731 });
1732
Minyue2013aec2015-05-13 14:14:42 +02001733 uint32_t ntp_secs = 0;
1734 uint32_t ntp_frac = 0;
1735 uint32_t rtp_timestamp = 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001736 if (0 !=
1737 _rtpRtcpModule->RemoteNTP(&ntp_secs, &ntp_frac, NULL, NULL,
1738 &rtp_timestamp)) {
Minyue2013aec2015-05-13 14:14:42 +02001739 // Waiting for RTCP.
1740 return 0;
1741 }
1742
stefan@webrtc.org8e24d872014-09-02 18:58:24 +00001743 {
tommi31fc21f2016-01-21 10:37:37 -08001744 rtc::CritScope lock(&ts_stats_lock_);
minyue@webrtc.org2c0cdbc2014-10-09 10:52:43 +00001745 ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp);
stefan@webrtc.org8e24d872014-09-02 18:58:24 +00001746 }
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001747 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001748}
1749
niklase@google.com470e71d2011-07-07 08:21:25 +00001750int Channel::StartPlayingFileLocally(const char* fileName,
pbos@webrtc.org92135212013-05-14 08:31:39 +00001751 bool loop,
1752 FileFormats format,
1753 int startPosition,
1754 float volumeScaling,
1755 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08001756 const CodecInst* codecInst) {
1757 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1758 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
1759 " format=%d, volumeScaling=%5.3f, startPosition=%d, "
1760 "stopPosition=%d)",
1761 fileName, loop, format, volumeScaling, startPosition,
1762 stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00001763
kwiberg55b97fe2016-01-28 05:22:45 -08001764 if (channel_state_.Get().output_file_playing) {
1765 _engineStatisticsPtr->SetLastError(
1766 VE_ALREADY_PLAYING, kTraceError,
1767 "StartPlayingFileLocally() is already playing");
1768 return -1;
1769 }
1770
1771 {
1772 rtc::CritScope cs(&_fileCritSect);
1773
kwiberg5a25d952016-08-17 07:31:12 -07001774 if (output_file_player_) {
1775 output_file_player_->RegisterModuleFileCallback(NULL);
1776 output_file_player_.reset();
niklase@google.com470e71d2011-07-07 08:21:25 +00001777 }
1778
kwiberg5b356f42016-09-08 04:32:33 -07001779 output_file_player_ = FilePlayer::CreateFilePlayer(
kwiberg55b97fe2016-01-28 05:22:45 -08001780 _outputFilePlayerId, (const FileFormats)format);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00001781
kwiberg5a25d952016-08-17 07:31:12 -07001782 if (!output_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08001783 _engineStatisticsPtr->SetLastError(
1784 VE_INVALID_ARGUMENT, kTraceError,
1785 "StartPlayingFileLocally() filePlayer format is not correct");
1786 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001787 }
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001788
kwiberg55b97fe2016-01-28 05:22:45 -08001789 const uint32_t notificationTime(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00001790
kwiberg5a25d952016-08-17 07:31:12 -07001791 if (output_file_player_->StartPlayingFile(
kwiberg55b97fe2016-01-28 05:22:45 -08001792 fileName, loop, startPosition, volumeScaling, notificationTime,
1793 stopPosition, (const CodecInst*)codecInst) != 0) {
1794 _engineStatisticsPtr->SetLastError(
1795 VE_BAD_FILE, kTraceError,
1796 "StartPlayingFile() failed to start file playout");
kwiberg5a25d952016-08-17 07:31:12 -07001797 output_file_player_->StopPlayingFile();
1798 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001799 return -1;
1800 }
kwiberg5a25d952016-08-17 07:31:12 -07001801 output_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08001802 channel_state_.SetOutputFilePlaying(true);
1803 }
1804
1805 if (RegisterFilePlayingToMixer() != 0)
1806 return -1;
1807
1808 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001809}
1810
1811int Channel::StartPlayingFileLocally(InStream* stream,
pbos@webrtc.org92135212013-05-14 08:31:39 +00001812 FileFormats format,
1813 int startPosition,
1814 float volumeScaling,
1815 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08001816 const CodecInst* codecInst) {
1817 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1818 "Channel::StartPlayingFileLocally(format=%d,"
1819 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
1820 format, volumeScaling, startPosition, stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00001821
kwiberg55b97fe2016-01-28 05:22:45 -08001822 if (stream == NULL) {
1823 _engineStatisticsPtr->SetLastError(
1824 VE_BAD_FILE, kTraceError,
1825 "StartPlayingFileLocally() NULL as input stream");
1826 return -1;
1827 }
1828
1829 if (channel_state_.Get().output_file_playing) {
1830 _engineStatisticsPtr->SetLastError(
1831 VE_ALREADY_PLAYING, kTraceError,
1832 "StartPlayingFileLocally() is already playing");
1833 return -1;
1834 }
1835
1836 {
1837 rtc::CritScope cs(&_fileCritSect);
1838
1839 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07001840 if (output_file_player_) {
1841 output_file_player_->RegisterModuleFileCallback(NULL);
1842 output_file_player_.reset();
niklase@google.com470e71d2011-07-07 08:21:25 +00001843 }
1844
kwiberg55b97fe2016-01-28 05:22:45 -08001845 // Create the instance
kwiberg5b356f42016-09-08 04:32:33 -07001846 output_file_player_ = FilePlayer::CreateFilePlayer(
kwiberg55b97fe2016-01-28 05:22:45 -08001847 _outputFilePlayerId, (const FileFormats)format);
niklase@google.com470e71d2011-07-07 08:21:25 +00001848
kwiberg5a25d952016-08-17 07:31:12 -07001849 if (!output_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08001850 _engineStatisticsPtr->SetLastError(
1851 VE_INVALID_ARGUMENT, kTraceError,
1852 "StartPlayingFileLocally() filePlayer format isnot correct");
1853 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001854 }
1855
kwiberg55b97fe2016-01-28 05:22:45 -08001856 const uint32_t notificationTime(0);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00001857
kwiberg4ec01d92016-08-22 08:43:54 -07001858 if (output_file_player_->StartPlayingFile(stream, startPosition,
kwiberg5a25d952016-08-17 07:31:12 -07001859 volumeScaling, notificationTime,
1860 stopPosition, codecInst) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001861 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
1862 "StartPlayingFile() failed to "
1863 "start file playout");
kwiberg5a25d952016-08-17 07:31:12 -07001864 output_file_player_->StopPlayingFile();
1865 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001866 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001867 }
kwiberg5a25d952016-08-17 07:31:12 -07001868 output_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08001869 channel_state_.SetOutputFilePlaying(true);
1870 }
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001871
kwiberg55b97fe2016-01-28 05:22:45 -08001872 if (RegisterFilePlayingToMixer() != 0)
1873 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001874
kwiberg55b97fe2016-01-28 05:22:45 -08001875 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001876}
1877
kwiberg55b97fe2016-01-28 05:22:45 -08001878int Channel::StopPlayingFileLocally() {
1879 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1880 "Channel::StopPlayingFileLocally()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001881
kwiberg55b97fe2016-01-28 05:22:45 -08001882 if (!channel_state_.Get().output_file_playing) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001883 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001884 }
1885
1886 {
1887 rtc::CritScope cs(&_fileCritSect);
1888
kwiberg5a25d952016-08-17 07:31:12 -07001889 if (output_file_player_->StopPlayingFile() != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001890 _engineStatisticsPtr->SetLastError(
1891 VE_STOP_RECORDING_FAILED, kTraceError,
1892 "StopPlayingFile() could not stop playing");
1893 return -1;
1894 }
kwiberg5a25d952016-08-17 07:31:12 -07001895 output_file_player_->RegisterModuleFileCallback(NULL);
1896 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001897 channel_state_.SetOutputFilePlaying(false);
1898 }
1899 // _fileCritSect cannot be taken while calling
1900 // SetAnonymousMixibilityStatus. Refer to comments in
1901 // StartPlayingFileLocally(const char* ...) for more details.
1902 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0) {
1903 _engineStatisticsPtr->SetLastError(
1904 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1905 "StopPlayingFile() failed to stop participant from playing as"
1906 "file in the mixer");
1907 return -1;
1908 }
1909
1910 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001911}
1912
kwiberg55b97fe2016-01-28 05:22:45 -08001913int Channel::IsPlayingFileLocally() const {
1914 return channel_state_.Get().output_file_playing;
niklase@google.com470e71d2011-07-07 08:21:25 +00001915}
1916
kwiberg55b97fe2016-01-28 05:22:45 -08001917int Channel::RegisterFilePlayingToMixer() {
1918 // Return success for not registering for file playing to mixer if:
1919 // 1. playing file before playout is started on that channel.
1920 // 2. starting playout without file playing on that channel.
1921 if (!channel_state_.Get().playing ||
1922 !channel_state_.Get().output_file_playing) {
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001923 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001924 }
1925
1926 // |_fileCritSect| cannot be taken while calling
1927 // SetAnonymousMixabilityStatus() since as soon as the participant is added
1928 // frames can be pulled by the mixer. Since the frames are generated from
1929 // the file, _fileCritSect will be taken. This would result in a deadlock.
1930 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0) {
1931 channel_state_.SetOutputFilePlaying(false);
1932 rtc::CritScope cs(&_fileCritSect);
1933 _engineStatisticsPtr->SetLastError(
1934 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1935 "StartPlayingFile() failed to add participant as file to mixer");
kwiberg5a25d952016-08-17 07:31:12 -07001936 output_file_player_->StopPlayingFile();
1937 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001938 return -1;
1939 }
1940
1941 return 0;
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001942}
1943
niklase@google.com470e71d2011-07-07 08:21:25 +00001944int Channel::StartPlayingFileAsMicrophone(const char* fileName,
pbos@webrtc.org92135212013-05-14 08:31:39 +00001945 bool loop,
1946 FileFormats format,
1947 int startPosition,
1948 float volumeScaling,
1949 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08001950 const CodecInst* codecInst) {
1951 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1952 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
1953 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
1954 "stopPosition=%d)",
1955 fileName, loop, format, volumeScaling, startPosition,
1956 stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00001957
kwiberg55b97fe2016-01-28 05:22:45 -08001958 rtc::CritScope cs(&_fileCritSect);
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +00001959
kwiberg55b97fe2016-01-28 05:22:45 -08001960 if (channel_state_.Get().input_file_playing) {
1961 _engineStatisticsPtr->SetLastError(
1962 VE_ALREADY_PLAYING, kTraceWarning,
1963 "StartPlayingFileAsMicrophone() filePlayer is playing");
niklase@google.com470e71d2011-07-07 08:21:25 +00001964 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001965 }
1966
1967 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07001968 if (input_file_player_) {
1969 input_file_player_->RegisterModuleFileCallback(NULL);
1970 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001971 }
1972
1973 // Create the instance
kwiberg5b356f42016-09-08 04:32:33 -07001974 input_file_player_ = FilePlayer::CreateFilePlayer(_inputFilePlayerId,
kwiberg5a25d952016-08-17 07:31:12 -07001975 (const FileFormats)format);
kwiberg55b97fe2016-01-28 05:22:45 -08001976
kwiberg5a25d952016-08-17 07:31:12 -07001977 if (!input_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08001978 _engineStatisticsPtr->SetLastError(
1979 VE_INVALID_ARGUMENT, kTraceError,
1980 "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
1981 return -1;
1982 }
1983
1984 const uint32_t notificationTime(0);
1985
kwiberg5a25d952016-08-17 07:31:12 -07001986 if (input_file_player_->StartPlayingFile(
kwiberg55b97fe2016-01-28 05:22:45 -08001987 fileName, loop, startPosition, volumeScaling, notificationTime,
1988 stopPosition, (const CodecInst*)codecInst) != 0) {
1989 _engineStatisticsPtr->SetLastError(
1990 VE_BAD_FILE, kTraceError,
1991 "StartPlayingFile() failed to start file playout");
kwiberg5a25d952016-08-17 07:31:12 -07001992 input_file_player_->StopPlayingFile();
1993 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001994 return -1;
1995 }
kwiberg5a25d952016-08-17 07:31:12 -07001996 input_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08001997 channel_state_.SetInputFilePlaying(true);
1998
1999 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002000}
2001
2002int Channel::StartPlayingFileAsMicrophone(InStream* stream,
pbos@webrtc.org92135212013-05-14 08:31:39 +00002003 FileFormats format,
2004 int startPosition,
2005 float volumeScaling,
2006 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08002007 const CodecInst* codecInst) {
2008 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2009 "Channel::StartPlayingFileAsMicrophone(format=%d, "
2010 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
2011 format, volumeScaling, startPosition, stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00002012
kwiberg55b97fe2016-01-28 05:22:45 -08002013 if (stream == NULL) {
2014 _engineStatisticsPtr->SetLastError(
2015 VE_BAD_FILE, kTraceError,
2016 "StartPlayingFileAsMicrophone NULL as input stream");
2017 return -1;
2018 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002019
kwiberg55b97fe2016-01-28 05:22:45 -08002020 rtc::CritScope cs(&_fileCritSect);
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +00002021
kwiberg55b97fe2016-01-28 05:22:45 -08002022 if (channel_state_.Get().input_file_playing) {
2023 _engineStatisticsPtr->SetLastError(
2024 VE_ALREADY_PLAYING, kTraceWarning,
2025 "StartPlayingFileAsMicrophone() is playing");
niklase@google.com470e71d2011-07-07 08:21:25 +00002026 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08002027 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002028
kwiberg55b97fe2016-01-28 05:22:45 -08002029 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07002030 if (input_file_player_) {
2031 input_file_player_->RegisterModuleFileCallback(NULL);
2032 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002033 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002034
kwiberg55b97fe2016-01-28 05:22:45 -08002035 // Create the instance
kwiberg5b356f42016-09-08 04:32:33 -07002036 input_file_player_ = FilePlayer::CreateFilePlayer(_inputFilePlayerId,
kwiberg5a25d952016-08-17 07:31:12 -07002037 (const FileFormats)format);
kwiberg55b97fe2016-01-28 05:22:45 -08002038
kwiberg5a25d952016-08-17 07:31:12 -07002039 if (!input_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002040 _engineStatisticsPtr->SetLastError(
2041 VE_INVALID_ARGUMENT, kTraceError,
2042 "StartPlayingInputFile() filePlayer format isnot correct");
2043 return -1;
2044 }
2045
2046 const uint32_t notificationTime(0);
2047
kwiberg4ec01d92016-08-22 08:43:54 -07002048 if (input_file_player_->StartPlayingFile(stream, startPosition, volumeScaling,
2049 notificationTime, stopPosition,
2050 codecInst) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002051 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2052 "StartPlayingFile() failed to start "
2053 "file playout");
kwiberg5a25d952016-08-17 07:31:12 -07002054 input_file_player_->StopPlayingFile();
2055 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002056 return -1;
2057 }
2058
kwiberg5a25d952016-08-17 07:31:12 -07002059 input_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08002060 channel_state_.SetInputFilePlaying(true);
2061
2062 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002063}
2064
kwiberg55b97fe2016-01-28 05:22:45 -08002065int Channel::StopPlayingFileAsMicrophone() {
2066 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2067 "Channel::StopPlayingFileAsMicrophone()");
2068
2069 rtc::CritScope cs(&_fileCritSect);
2070
2071 if (!channel_state_.Get().input_file_playing) {
2072 return 0;
2073 }
2074
kwiberg5a25d952016-08-17 07:31:12 -07002075 if (input_file_player_->StopPlayingFile() != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002076 _engineStatisticsPtr->SetLastError(
2077 VE_STOP_RECORDING_FAILED, kTraceError,
2078 "StopPlayingFile() could not stop playing");
2079 return -1;
2080 }
kwiberg5a25d952016-08-17 07:31:12 -07002081 input_file_player_->RegisterModuleFileCallback(NULL);
2082 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002083 channel_state_.SetInputFilePlaying(false);
2084
2085 return 0;
2086}
2087
2088int Channel::IsPlayingFileAsMicrophone() const {
2089 return channel_state_.Get().input_file_playing;
niklase@google.com470e71d2011-07-07 08:21:25 +00002090}
2091
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002092int Channel::StartRecordingPlayout(const char* fileName,
kwiberg55b97fe2016-01-28 05:22:45 -08002093 const CodecInst* codecInst) {
2094 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2095 "Channel::StartRecordingPlayout(fileName=%s)", fileName);
niklase@google.com470e71d2011-07-07 08:21:25 +00002096
kwiberg55b97fe2016-01-28 05:22:45 -08002097 if (_outputFileRecording) {
2098 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
2099 "StartRecordingPlayout() is already recording");
niklase@google.com470e71d2011-07-07 08:21:25 +00002100 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08002101 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002102
kwiberg55b97fe2016-01-28 05:22:45 -08002103 FileFormats format;
2104 const uint32_t notificationTime(0); // Not supported in VoE
2105 CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
niklase@google.com470e71d2011-07-07 08:21:25 +00002106
kwiberg55b97fe2016-01-28 05:22:45 -08002107 if ((codecInst != NULL) &&
2108 ((codecInst->channels < 1) || (codecInst->channels > 2))) {
2109 _engineStatisticsPtr->SetLastError(
2110 VE_BAD_ARGUMENT, kTraceError,
2111 "StartRecordingPlayout() invalid compression");
2112 return (-1);
2113 }
2114 if (codecInst == NULL) {
2115 format = kFileFormatPcm16kHzFile;
2116 codecInst = &dummyCodec;
2117 } else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
2118 (STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
2119 (STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
2120 format = kFileFormatWavFile;
2121 } else {
2122 format = kFileFormatCompressedFile;
2123 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002124
kwiberg55b97fe2016-01-28 05:22:45 -08002125 rtc::CritScope cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002126
kwiberg55b97fe2016-01-28 05:22:45 -08002127 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07002128 if (output_file_recorder_) {
2129 output_file_recorder_->RegisterModuleFileCallback(NULL);
2130 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002131 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002132
kwiberg5a25d952016-08-17 07:31:12 -07002133 output_file_recorder_ = FileRecorder::CreateFileRecorder(
kwiberg55b97fe2016-01-28 05:22:45 -08002134 _outputFileRecorderId, (const FileFormats)format);
kwiberg5a25d952016-08-17 07:31:12 -07002135 if (!output_file_recorder_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002136 _engineStatisticsPtr->SetLastError(
2137 VE_INVALID_ARGUMENT, kTraceError,
2138 "StartRecordingPlayout() fileRecorder format isnot correct");
2139 return -1;
2140 }
2141
kwiberg5a25d952016-08-17 07:31:12 -07002142 if (output_file_recorder_->StartRecordingAudioFile(
kwiberg55b97fe2016-01-28 05:22:45 -08002143 fileName, (const CodecInst&)*codecInst, notificationTime) != 0) {
2144 _engineStatisticsPtr->SetLastError(
2145 VE_BAD_FILE, kTraceError,
2146 "StartRecordingAudioFile() failed to start file recording");
kwiberg5a25d952016-08-17 07:31:12 -07002147 output_file_recorder_->StopRecording();
2148 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002149 return -1;
2150 }
kwiberg5a25d952016-08-17 07:31:12 -07002151 output_file_recorder_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08002152 _outputFileRecording = true;
2153
2154 return 0;
2155}
2156
2157int Channel::StartRecordingPlayout(OutStream* stream,
2158 const CodecInst* codecInst) {
2159 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2160 "Channel::StartRecordingPlayout()");
2161
2162 if (_outputFileRecording) {
2163 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
2164 "StartRecordingPlayout() is already recording");
niklase@google.com470e71d2011-07-07 08:21:25 +00002165 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08002166 }
2167
2168 FileFormats format;
2169 const uint32_t notificationTime(0); // Not supported in VoE
2170 CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
2171
2172 if (codecInst != NULL && codecInst->channels != 1) {
2173 _engineStatisticsPtr->SetLastError(
2174 VE_BAD_ARGUMENT, kTraceError,
2175 "StartRecordingPlayout() invalid compression");
2176 return (-1);
2177 }
2178 if (codecInst == NULL) {
2179 format = kFileFormatPcm16kHzFile;
2180 codecInst = &dummyCodec;
2181 } else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
2182 (STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
2183 (STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
2184 format = kFileFormatWavFile;
2185 } else {
2186 format = kFileFormatCompressedFile;
2187 }
2188
2189 rtc::CritScope cs(&_fileCritSect);
2190
2191 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07002192 if (output_file_recorder_) {
2193 output_file_recorder_->RegisterModuleFileCallback(NULL);
2194 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002195 }
2196
kwiberg5a25d952016-08-17 07:31:12 -07002197 output_file_recorder_ = FileRecorder::CreateFileRecorder(
kwiberg55b97fe2016-01-28 05:22:45 -08002198 _outputFileRecorderId, (const FileFormats)format);
kwiberg5a25d952016-08-17 07:31:12 -07002199 if (!output_file_recorder_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002200 _engineStatisticsPtr->SetLastError(
2201 VE_INVALID_ARGUMENT, kTraceError,
2202 "StartRecordingPlayout() fileRecorder format isnot correct");
2203 return -1;
2204 }
2205
kwiberg4ec01d92016-08-22 08:43:54 -07002206 if (output_file_recorder_->StartRecordingAudioFile(stream, *codecInst,
kwiberg5a25d952016-08-17 07:31:12 -07002207 notificationTime) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002208 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2209 "StartRecordingPlayout() failed to "
2210 "start file recording");
kwiberg5a25d952016-08-17 07:31:12 -07002211 output_file_recorder_->StopRecording();
2212 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002213 return -1;
2214 }
2215
kwiberg5a25d952016-08-17 07:31:12 -07002216 output_file_recorder_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08002217 _outputFileRecording = true;
2218
2219 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002220}
2221
kwiberg55b97fe2016-01-28 05:22:45 -08002222int Channel::StopRecordingPlayout() {
2223 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
2224 "Channel::StopRecordingPlayout()");
2225
2226 if (!_outputFileRecording) {
2227 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1),
2228 "StopRecordingPlayout() isnot recording");
2229 return -1;
2230 }
2231
2232 rtc::CritScope cs(&_fileCritSect);
2233
kwiberg5a25d952016-08-17 07:31:12 -07002234 if (output_file_recorder_->StopRecording() != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002235 _engineStatisticsPtr->SetLastError(
2236 VE_STOP_RECORDING_FAILED, kTraceError,
2237 "StopRecording() could not stop recording");
2238 return (-1);
2239 }
kwiberg5a25d952016-08-17 07:31:12 -07002240 output_file_recorder_->RegisterModuleFileCallback(NULL);
2241 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002242 _outputFileRecording = false;
2243
2244 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002245}
2246
kwiberg55b97fe2016-01-28 05:22:45 -08002247void Channel::SetMixWithMicStatus(bool mix) {
2248 rtc::CritScope cs(&_fileCritSect);
2249 _mixFileWithMicrophone = mix;
niklase@google.com470e71d2011-07-07 08:21:25 +00002250}
2251
kwiberg55b97fe2016-01-28 05:22:45 -08002252int Channel::GetSpeechOutputLevel(uint32_t& level) const {
2253 int8_t currentLevel = _outputAudioLevel.Level();
2254 level = static_cast<int32_t>(currentLevel);
2255 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002256}
2257
kwiberg55b97fe2016-01-28 05:22:45 -08002258int Channel::GetSpeechOutputLevelFullRange(uint32_t& level) const {
2259 int16_t currentLevel = _outputAudioLevel.LevelFullRange();
2260 level = static_cast<int32_t>(currentLevel);
2261 return 0;
2262}
2263
solenberg1c2af8e2016-03-24 10:36:00 -07002264int Channel::SetInputMute(bool enable) {
kwiberg55b97fe2016-01-28 05:22:45 -08002265 rtc::CritScope cs(&volume_settings_critsect_);
2266 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002267 "Channel::SetMute(enable=%d)", enable);
solenberg1c2af8e2016-03-24 10:36:00 -07002268 input_mute_ = enable;
kwiberg55b97fe2016-01-28 05:22:45 -08002269 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002270}
2271
solenberg1c2af8e2016-03-24 10:36:00 -07002272bool Channel::InputMute() const {
kwiberg55b97fe2016-01-28 05:22:45 -08002273 rtc::CritScope cs(&volume_settings_critsect_);
solenberg1c2af8e2016-03-24 10:36:00 -07002274 return input_mute_;
niklase@google.com470e71d2011-07-07 08:21:25 +00002275}
2276
kwiberg55b97fe2016-01-28 05:22:45 -08002277int Channel::SetOutputVolumePan(float left, float right) {
2278 rtc::CritScope cs(&volume_settings_critsect_);
2279 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002280 "Channel::SetOutputVolumePan()");
kwiberg55b97fe2016-01-28 05:22:45 -08002281 _panLeft = left;
2282 _panRight = right;
2283 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002284}
2285
kwiberg55b97fe2016-01-28 05:22:45 -08002286int Channel::GetOutputVolumePan(float& left, float& right) const {
2287 rtc::CritScope cs(&volume_settings_critsect_);
2288 left = _panLeft;
2289 right = _panRight;
2290 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002291}
2292
kwiberg55b97fe2016-01-28 05:22:45 -08002293int Channel::SetChannelOutputVolumeScaling(float scaling) {
2294 rtc::CritScope cs(&volume_settings_critsect_);
2295 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002296 "Channel::SetChannelOutputVolumeScaling()");
kwiberg55b97fe2016-01-28 05:22:45 -08002297 _outputGain = scaling;
2298 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002299}
2300
kwiberg55b97fe2016-01-28 05:22:45 -08002301int Channel::GetChannelOutputVolumeScaling(float& scaling) const {
2302 rtc::CritScope cs(&volume_settings_critsect_);
2303 scaling = _outputGain;
2304 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002305}
2306
solenberg8842c3e2016-03-11 03:06:41 -08002307int Channel::SendTelephoneEventOutband(int event, int duration_ms) {
kwiberg55b97fe2016-01-28 05:22:45 -08002308 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
solenberg8842c3e2016-03-11 03:06:41 -08002309 "Channel::SendTelephoneEventOutband(...)");
2310 RTC_DCHECK_LE(0, event);
2311 RTC_DCHECK_GE(255, event);
2312 RTC_DCHECK_LE(0, duration_ms);
2313 RTC_DCHECK_GE(65535, duration_ms);
kwiberg55b97fe2016-01-28 05:22:45 -08002314 if (!Sending()) {
2315 return -1;
2316 }
solenberg8842c3e2016-03-11 03:06:41 -08002317 if (_rtpRtcpModule->SendTelephoneEventOutband(
2318 event, duration_ms, kTelephoneEventAttenuationdB) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002319 _engineStatisticsPtr->SetLastError(
2320 VE_SEND_DTMF_FAILED, kTraceWarning,
2321 "SendTelephoneEventOutband() failed to send event");
2322 return -1;
2323 }
2324 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002325}
2326
solenbergffbbcac2016-11-17 05:25:37 -08002327int Channel::SetSendTelephoneEventPayloadType(int payload_type,
2328 int payload_frequency) {
kwiberg55b97fe2016-01-28 05:22:45 -08002329 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002330 "Channel::SetSendTelephoneEventPayloadType()");
solenberg31642aa2016-03-14 08:00:37 -07002331 RTC_DCHECK_LE(0, payload_type);
2332 RTC_DCHECK_GE(127, payload_type);
2333 CodecInst codec = {0};
solenberg31642aa2016-03-14 08:00:37 -07002334 codec.pltype = payload_type;
solenbergffbbcac2016-11-17 05:25:37 -08002335 codec.plfreq = payload_frequency;
kwiberg55b97fe2016-01-28 05:22:45 -08002336 memcpy(codec.plname, "telephone-event", 16);
2337 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
2338 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
2339 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
2340 _engineStatisticsPtr->SetLastError(
2341 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2342 "SetSendTelephoneEventPayloadType() failed to register send"
2343 "payload type");
2344 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002345 }
kwiberg55b97fe2016-01-28 05:22:45 -08002346 }
kwiberg55b97fe2016-01-28 05:22:45 -08002347 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002348}
2349
kwiberg55b97fe2016-01-28 05:22:45 -08002350int Channel::VoiceActivityIndicator(int& activity) {
2351 activity = _sendFrameType;
2352 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002353}
2354
kwiberg55b97fe2016-01-28 05:22:45 -08002355int Channel::SetLocalSSRC(unsigned int ssrc) {
2356 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2357 "Channel::SetLocalSSRC()");
2358 if (channel_state_.Get().sending) {
2359 _engineStatisticsPtr->SetLastError(VE_ALREADY_SENDING, kTraceError,
2360 "SetLocalSSRC() already sending");
2361 return -1;
2362 }
2363 _rtpRtcpModule->SetSSRC(ssrc);
2364 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002365}
2366
kwiberg55b97fe2016-01-28 05:22:45 -08002367int Channel::GetLocalSSRC(unsigned int& ssrc) {
2368 ssrc = _rtpRtcpModule->SSRC();
2369 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002370}
2371
kwiberg55b97fe2016-01-28 05:22:45 -08002372int Channel::GetRemoteSSRC(unsigned int& ssrc) {
2373 ssrc = rtp_receiver_->SSRC();
2374 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002375}
2376
wu@webrtc.orgebdb0e32014-03-06 23:49:08 +00002377int Channel::SetSendAudioLevelIndicationStatus(bool enable, unsigned char id) {
andrew@webrtc.orgf3930e92013-09-18 22:37:32 +00002378 _includeAudioLevelIndication = enable;
wu@webrtc.orgebdb0e32014-03-06 23:49:08 +00002379 return SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id);
niklase@google.com470e71d2011-07-07 08:21:25 +00002380}
andrew@webrtc.orgf3930e92013-09-18 22:37:32 +00002381
wu@webrtc.org93fd25c2014-04-24 20:33:08 +00002382int Channel::SetReceiveAudioLevelIndicationStatus(bool enable,
2383 unsigned char id) {
kwiberg55b97fe2016-01-28 05:22:45 -08002384 rtp_header_parser_->DeregisterRtpHeaderExtension(kRtpExtensionAudioLevel);
2385 if (enable &&
2386 !rtp_header_parser_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
2387 id)) {
wu@webrtc.org93fd25c2014-04-24 20:33:08 +00002388 return -1;
2389 }
2390 return 0;
2391}
2392
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002393void Channel::EnableSendTransportSequenceNumber(int id) {
2394 int ret =
2395 SetSendRtpHeaderExtension(true, kRtpExtensionTransportSequenceNumber, id);
2396 RTC_DCHECK_EQ(0, ret);
2397}
2398
stefan3313ec92016-01-21 06:32:43 -08002399void Channel::EnableReceiveTransportSequenceNumber(int id) {
2400 rtp_header_parser_->DeregisterRtpHeaderExtension(
2401 kRtpExtensionTransportSequenceNumber);
2402 bool ret = rtp_header_parser_->RegisterRtpHeaderExtension(
2403 kRtpExtensionTransportSequenceNumber, id);
2404 RTC_DCHECK(ret);
2405}
2406
stefanbba9dec2016-02-01 04:39:55 -08002407void Channel::RegisterSenderCongestionControlObjects(
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002408 RtpPacketSender* rtp_packet_sender,
2409 TransportFeedbackObserver* transport_feedback_observer,
stefan7de8d642017-02-07 07:14:08 -08002410 PacketRouter* packet_router,
2411 RtcpBandwidthObserver* bandwidth_observer) {
stefanbba9dec2016-02-01 04:39:55 -08002412 RTC_DCHECK(rtp_packet_sender);
2413 RTC_DCHECK(transport_feedback_observer);
2414 RTC_DCHECK(packet_router && !packet_router_);
stefan7de8d642017-02-07 07:14:08 -08002415 rtcp_observer_->SetBandwidthObserver(bandwidth_observer);
stefanbba9dec2016-02-01 04:39:55 -08002416 feedback_observer_proxy_->SetTransportFeedbackObserver(
2417 transport_feedback_observer);
2418 seq_num_allocator_proxy_->SetSequenceNumberAllocator(packet_router);
2419 rtp_packet_sender_proxy_->SetPacketSender(rtp_packet_sender);
2420 _rtpRtcpModule->SetStorePacketsStatus(true, 600);
Peter Boström3dd5d1d2016-02-25 16:56:48 +01002421 packet_router->AddRtpModule(_rtpRtcpModule.get());
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002422 packet_router_ = packet_router;
2423}
2424
stefanbba9dec2016-02-01 04:39:55 -08002425void Channel::RegisterReceiverCongestionControlObjects(
2426 PacketRouter* packet_router) {
2427 RTC_DCHECK(packet_router && !packet_router_);
Peter Boström3dd5d1d2016-02-25 16:56:48 +01002428 packet_router->AddRtpModule(_rtpRtcpModule.get());
stefanbba9dec2016-02-01 04:39:55 -08002429 packet_router_ = packet_router;
2430}
2431
2432void Channel::ResetCongestionControlObjects() {
2433 RTC_DCHECK(packet_router_);
2434 _rtpRtcpModule->SetStorePacketsStatus(false, 600);
stefan7de8d642017-02-07 07:14:08 -08002435 rtcp_observer_->SetBandwidthObserver(nullptr);
stefanbba9dec2016-02-01 04:39:55 -08002436 feedback_observer_proxy_->SetTransportFeedbackObserver(nullptr);
2437 seq_num_allocator_proxy_->SetSequenceNumberAllocator(nullptr);
Peter Boström3dd5d1d2016-02-25 16:56:48 +01002438 packet_router_->RemoveRtpModule(_rtpRtcpModule.get());
stefanbba9dec2016-02-01 04:39:55 -08002439 packet_router_ = nullptr;
2440 rtp_packet_sender_proxy_->SetPacketSender(nullptr);
2441}
2442
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00002443void Channel::SetRTCPStatus(bool enable) {
2444 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2445 "Channel::SetRTCPStatus()");
pbosda903ea2015-10-02 02:36:56 -07002446 _rtpRtcpModule->SetRTCPStatus(enable ? RtcpMode::kCompound : RtcpMode::kOff);
niklase@google.com470e71d2011-07-07 08:21:25 +00002447}
2448
kwiberg55b97fe2016-01-28 05:22:45 -08002449int Channel::GetRTCPStatus(bool& enabled) {
pbosda903ea2015-10-02 02:36:56 -07002450 RtcpMode method = _rtpRtcpModule->RTCP();
2451 enabled = (method != RtcpMode::kOff);
kwiberg55b97fe2016-01-28 05:22:45 -08002452 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002453}
2454
kwiberg55b97fe2016-01-28 05:22:45 -08002455int Channel::SetRTCP_CNAME(const char cName[256]) {
2456 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2457 "Channel::SetRTCP_CNAME()");
2458 if (_rtpRtcpModule->SetCNAME(cName) != 0) {
2459 _engineStatisticsPtr->SetLastError(
2460 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2461 "SetRTCP_CNAME() failed to set RTCP CNAME");
2462 return -1;
2463 }
2464 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002465}
2466
kwiberg55b97fe2016-01-28 05:22:45 -08002467int Channel::GetRemoteRTCP_CNAME(char cName[256]) {
2468 if (cName == NULL) {
2469 _engineStatisticsPtr->SetLastError(
2470 VE_INVALID_ARGUMENT, kTraceError,
2471 "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
2472 return -1;
2473 }
2474 char cname[RTCP_CNAME_SIZE];
2475 const uint32_t remoteSSRC = rtp_receiver_->SSRC();
2476 if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0) {
2477 _engineStatisticsPtr->SetLastError(
2478 VE_CANNOT_RETRIEVE_CNAME, kTraceError,
2479 "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
2480 return -1;
2481 }
2482 strcpy(cName, cname);
2483 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002484}
2485
kwiberg55b97fe2016-01-28 05:22:45 -08002486int Channel::SendApplicationDefinedRTCPPacket(
2487 unsigned char subType,
2488 unsigned int name,
2489 const char* data,
2490 unsigned short dataLengthInBytes) {
2491 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2492 "Channel::SendApplicationDefinedRTCPPacket()");
2493 if (!channel_state_.Get().sending) {
2494 _engineStatisticsPtr->SetLastError(
2495 VE_NOT_SENDING, kTraceError,
2496 "SendApplicationDefinedRTCPPacket() not sending");
2497 return -1;
2498 }
2499 if (NULL == data) {
2500 _engineStatisticsPtr->SetLastError(
2501 VE_INVALID_ARGUMENT, kTraceError,
2502 "SendApplicationDefinedRTCPPacket() invalid data value");
2503 return -1;
2504 }
2505 if (dataLengthInBytes % 4 != 0) {
2506 _engineStatisticsPtr->SetLastError(
2507 VE_INVALID_ARGUMENT, kTraceError,
2508 "SendApplicationDefinedRTCPPacket() invalid length value");
2509 return -1;
2510 }
2511 RtcpMode status = _rtpRtcpModule->RTCP();
2512 if (status == RtcpMode::kOff) {
2513 _engineStatisticsPtr->SetLastError(
2514 VE_RTCP_ERROR, kTraceError,
2515 "SendApplicationDefinedRTCPPacket() RTCP is disabled");
2516 return -1;
2517 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002518
kwiberg55b97fe2016-01-28 05:22:45 -08002519 // Create and schedule the RTCP APP packet for transmission
2520 if (_rtpRtcpModule->SetRTCPApplicationSpecificData(
2521 subType, name, (const unsigned char*)data, dataLengthInBytes) != 0) {
2522 _engineStatisticsPtr->SetLastError(
2523 VE_SEND_ERROR, kTraceError,
2524 "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
2525 return -1;
2526 }
2527 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002528}
2529
henrika@webrtc.org8a2fc882012-08-22 08:53:55 +00002530int Channel::GetRemoteRTCPReportBlocks(
2531 std::vector<ReportBlock>* report_blocks) {
2532 if (report_blocks == NULL) {
kwiberg55b97fe2016-01-28 05:22:45 -08002533 _engineStatisticsPtr->SetLastError(
2534 VE_INVALID_ARGUMENT, kTraceError,
2535 "GetRemoteRTCPReportBlock()s invalid report_blocks.");
henrika@webrtc.org8a2fc882012-08-22 08:53:55 +00002536 return -1;
2537 }
2538
2539 // Get the report blocks from the latest received RTCP Sender or Receiver
2540 // Report. Each element in the vector contains the sender's SSRC and a
2541 // report block according to RFC 3550.
2542 std::vector<RTCPReportBlock> rtcp_report_blocks;
2543 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) {
henrika@webrtc.org8a2fc882012-08-22 08:53:55 +00002544 return -1;
2545 }
2546
2547 if (rtcp_report_blocks.empty())
2548 return 0;
2549
2550 std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
2551 for (; it != rtcp_report_blocks.end(); ++it) {
2552 ReportBlock report_block;
2553 report_block.sender_SSRC = it->remoteSSRC;
2554 report_block.source_SSRC = it->sourceSSRC;
2555 report_block.fraction_lost = it->fractionLost;
2556 report_block.cumulative_num_packets_lost = it->cumulativeLost;
2557 report_block.extended_highest_sequence_number = it->extendedHighSeqNum;
2558 report_block.interarrival_jitter = it->jitter;
2559 report_block.last_SR_timestamp = it->lastSR;
2560 report_block.delay_since_last_SR = it->delaySinceLastSR;
2561 report_blocks->push_back(report_block);
2562 }
2563 return 0;
2564}
2565
kwiberg55b97fe2016-01-28 05:22:45 -08002566int Channel::GetRTPStatistics(CallStatistics& stats) {
2567 // --- RtcpStatistics
niklase@google.com470e71d2011-07-07 08:21:25 +00002568
kwiberg55b97fe2016-01-28 05:22:45 -08002569 // The jitter statistics is updated for each received RTP packet and is
2570 // based on received packets.
2571 RtcpStatistics statistics;
2572 StreamStatistician* statistician =
2573 rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
Peter Boström59013bc2016-02-12 11:35:08 +01002574 if (statistician) {
2575 statistician->GetStatistics(&statistics,
2576 _rtpRtcpModule->RTCP() == RtcpMode::kOff);
kwiberg55b97fe2016-01-28 05:22:45 -08002577 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002578
kwiberg55b97fe2016-01-28 05:22:45 -08002579 stats.fractionLost = statistics.fraction_lost;
2580 stats.cumulativeLost = statistics.cumulative_lost;
2581 stats.extendedMax = statistics.extended_max_sequence_number;
2582 stats.jitterSamples = statistics.jitter;
niklase@google.com470e71d2011-07-07 08:21:25 +00002583
kwiberg55b97fe2016-01-28 05:22:45 -08002584 // --- RTT
2585 stats.rttMs = GetRTT(true);
niklase@google.com470e71d2011-07-07 08:21:25 +00002586
kwiberg55b97fe2016-01-28 05:22:45 -08002587 // --- Data counters
niklase@google.com470e71d2011-07-07 08:21:25 +00002588
kwiberg55b97fe2016-01-28 05:22:45 -08002589 size_t bytesSent(0);
2590 uint32_t packetsSent(0);
2591 size_t bytesReceived(0);
2592 uint32_t packetsReceived(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00002593
kwiberg55b97fe2016-01-28 05:22:45 -08002594 if (statistician) {
2595 statistician->GetDataCounters(&bytesReceived, &packetsReceived);
2596 }
wu@webrtc.org822fbd82013-08-15 23:38:54 +00002597
kwiberg55b97fe2016-01-28 05:22:45 -08002598 if (_rtpRtcpModule->DataCountersRTP(&bytesSent, &packetsSent) != 0) {
2599 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2600 "GetRTPStatistics() failed to retrieve RTP datacounters =>"
2601 " output will not be complete");
2602 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002603
kwiberg55b97fe2016-01-28 05:22:45 -08002604 stats.bytesSent = bytesSent;
2605 stats.packetsSent = packetsSent;
2606 stats.bytesReceived = bytesReceived;
2607 stats.packetsReceived = packetsReceived;
niklase@google.com470e71d2011-07-07 08:21:25 +00002608
kwiberg55b97fe2016-01-28 05:22:45 -08002609 // --- Timestamps
2610 {
2611 rtc::CritScope lock(&ts_stats_lock_);
2612 stats.capture_start_ntp_time_ms_ = capture_start_ntp_time_ms_;
2613 }
2614 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002615}
2616
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00002617int Channel::SetCodecFECStatus(bool enable) {
2618 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2619 "Channel::SetCodecFECStatus()");
2620
kwibergc8d071e2016-04-06 12:22:38 -07002621 if (!codec_manager_.SetCodecFEC(enable) ||
2622 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00002623 _engineStatisticsPtr->SetLastError(
2624 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2625 "SetCodecFECStatus() failed to set FEC state");
2626 return -1;
2627 }
2628 return 0;
2629}
2630
2631bool Channel::GetCodecFECStatus() {
kwibergc8d071e2016-04-06 12:22:38 -07002632 return codec_manager_.GetStackParams()->use_codec_fec;
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00002633}
2634
pwestin@webrtc.orgdb249952013-06-05 15:33:20 +00002635void Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) {
2636 // None of these functions can fail.
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002637 // If pacing is enabled we always store packets.
2638 if (!pacing_enabled_)
2639 _rtpRtcpModule->SetStorePacketsStatus(enable, maxNumberOfPackets);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00002640 rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets);
pwestin@webrtc.orgd30859e2013-06-06 21:09:01 +00002641 if (enable)
andrew@webrtc.orgeb524d92013-09-23 23:02:24 +00002642 audio_coding_->EnableNack(maxNumberOfPackets);
pwestin@webrtc.orgd30859e2013-06-06 21:09:01 +00002643 else
andrew@webrtc.orgeb524d92013-09-23 23:02:24 +00002644 audio_coding_->DisableNack();
pwestin@webrtc.orgdb249952013-06-05 15:33:20 +00002645}
2646
pwestin@webrtc.orgd30859e2013-06-06 21:09:01 +00002647// Called when we are missing one or more packets.
2648int Channel::ResendPackets(const uint16_t* sequence_numbers, int length) {
pwestin@webrtc.orgdb249952013-06-05 15:33:20 +00002649 return _rtpRtcpModule->SendNACK(sequence_numbers, length);
2650}
2651
kwiberg55b97fe2016-01-28 05:22:45 -08002652uint32_t Channel::Demultiplex(const AudioFrame& audioFrame) {
2653 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2654 "Channel::Demultiplex()");
2655 _audioFrame.CopyFrom(audioFrame);
2656 _audioFrame.id_ = _channelId;
2657 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002658}
2659
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002660void Channel::Demultiplex(const int16_t* audio_data,
xians@webrtc.org8fff1f02013-07-31 16:27:42 +00002661 int sample_rate,
Peter Kastingdce40cf2015-08-24 14:52:23 -07002662 size_t number_of_frames,
Peter Kasting69558702016-01-12 16:26:35 -08002663 size_t number_of_channels) {
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002664 CodecInst codec;
2665 GetSendCodec(codec);
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002666
Alejandro Luebscdfe20b2015-09-23 12:49:12 -07002667 // Never upsample or upmix the capture signal here. This should be done at the
2668 // end of the send chain.
2669 _audioFrame.sample_rate_hz_ = std::min(codec.plfreq, sample_rate);
2670 _audioFrame.num_channels_ = std::min(number_of_channels, codec.channels);
2671 RemixAndResample(audio_data, number_of_frames, number_of_channels,
2672 sample_rate, &input_resampler_, &_audioFrame);
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002673}
2674
kwiberg55b97fe2016-01-28 05:22:45 -08002675uint32_t Channel::PrepareEncodeAndSend(int mixingFrequency) {
2676 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2677 "Channel::PrepareEncodeAndSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00002678
kwiberg55b97fe2016-01-28 05:22:45 -08002679 if (_audioFrame.samples_per_channel_ == 0) {
2680 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2681 "Channel::PrepareEncodeAndSend() invalid audio frame");
2682 return 0xFFFFFFFF;
2683 }
2684
2685 if (channel_state_.Get().input_file_playing) {
2686 MixOrReplaceAudioWithFile(mixingFrequency);
2687 }
2688
solenberg1c2af8e2016-03-24 10:36:00 -07002689 bool is_muted = InputMute(); // Cache locally as InputMute() takes a lock.
2690 AudioFrameOperations::Mute(&_audioFrame, previous_frame_muted_, is_muted);
kwiberg55b97fe2016-01-28 05:22:45 -08002691
kwiberg55b97fe2016-01-28 05:22:45 -08002692 if (_includeAudioLevelIndication) {
2693 size_t length =
2694 _audioFrame.samples_per_channel_ * _audioFrame.num_channels_;
Tommi60c4e0a2016-05-26 21:35:27 +02002695 RTC_CHECK_LE(length, sizeof(_audioFrame.data_));
solenberg1c2af8e2016-03-24 10:36:00 -07002696 if (is_muted && previous_frame_muted_) {
henrik.lundin50499422016-11-29 04:26:24 -08002697 rms_level_.AnalyzeMuted(length);
kwiberg55b97fe2016-01-28 05:22:45 -08002698 } else {
henrik.lundin50499422016-11-29 04:26:24 -08002699 rms_level_.Analyze(
2700 rtc::ArrayView<const int16_t>(_audioFrame.data_, length));
niklase@google.com470e71d2011-07-07 08:21:25 +00002701 }
kwiberg55b97fe2016-01-28 05:22:45 -08002702 }
solenberg1c2af8e2016-03-24 10:36:00 -07002703 previous_frame_muted_ = is_muted;
niklase@google.com470e71d2011-07-07 08:21:25 +00002704
kwiberg55b97fe2016-01-28 05:22:45 -08002705 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002706}
2707
kwiberg55b97fe2016-01-28 05:22:45 -08002708uint32_t Channel::EncodeAndSend() {
2709 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2710 "Channel::EncodeAndSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00002711
kwiberg55b97fe2016-01-28 05:22:45 -08002712 assert(_audioFrame.num_channels_ <= 2);
2713 if (_audioFrame.samples_per_channel_ == 0) {
2714 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2715 "Channel::EncodeAndSend() invalid audio frame");
2716 return 0xFFFFFFFF;
2717 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002718
kwiberg55b97fe2016-01-28 05:22:45 -08002719 _audioFrame.id_ = _channelId;
niklase@google.com470e71d2011-07-07 08:21:25 +00002720
kwiberg55b97fe2016-01-28 05:22:45 -08002721 // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
niklase@google.com470e71d2011-07-07 08:21:25 +00002722
kwiberg55b97fe2016-01-28 05:22:45 -08002723 // The ACM resamples internally.
2724 _audioFrame.timestamp_ = _timeStamp;
2725 // This call will trigger AudioPacketizationCallback::SendData if encoding
2726 // is done and payload is ready for packetization and transmission.
2727 // Otherwise, it will return without invoking the callback.
2728 if (audio_coding_->Add10MsData((AudioFrame&)_audioFrame) < 0) {
2729 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
2730 "Channel::EncodeAndSend() ACM encoding failed");
2731 return 0xFFFFFFFF;
2732 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002733
kwiberg55b97fe2016-01-28 05:22:45 -08002734 _timeStamp += static_cast<uint32_t>(_audioFrame.samples_per_channel_);
2735 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002736}
2737
solenberg7602aab2016-11-14 11:30:07 -08002738void Channel::set_associate_send_channel(const ChannelOwner& channel) {
2739 RTC_DCHECK(!channel.channel() ||
2740 channel.channel()->ChannelId() != _channelId);
2741 rtc::CritScope lock(&assoc_send_channel_lock_);
2742 associate_send_channel_ = channel;
2743}
2744
Minyue2013aec2015-05-13 14:14:42 +02002745void Channel::DisassociateSendChannel(int channel_id) {
tommi31fc21f2016-01-21 10:37:37 -08002746 rtc::CritScope lock(&assoc_send_channel_lock_);
Minyue2013aec2015-05-13 14:14:42 +02002747 Channel* channel = associate_send_channel_.channel();
2748 if (channel && channel->ChannelId() == channel_id) {
2749 // If this channel is associated with a send channel of the specified
2750 // Channel ID, disassociate with it.
2751 ChannelOwner ref(NULL);
2752 associate_send_channel_ = ref;
2753 }
2754}
2755
ivoc14d5dbe2016-07-04 07:06:55 -07002756void Channel::SetRtcEventLog(RtcEventLog* event_log) {
2757 event_log_proxy_->SetEventLog(event_log);
2758}
2759
michaelt9332b7d2016-11-30 07:51:13 -08002760void Channel::SetRtcpRttStats(RtcpRttStats* rtcp_rtt_stats) {
2761 rtcp_rtt_stats_proxy_->SetRtcpRttStats(rtcp_rtt_stats);
2762}
2763
nisse284542b2017-01-10 08:58:32 -08002764void Channel::UpdateOverheadForEncoder() {
hbos3fd31fe2017-02-28 05:43:16 -08002765 size_t overhead_per_packet =
2766 transport_overhead_per_packet_ + rtp_overhead_per_packet_;
nisse284542b2017-01-10 08:58:32 -08002767 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
2768 if (*encoder) {
hbos3fd31fe2017-02-28 05:43:16 -08002769 (*encoder)->OnReceivedOverhead(overhead_per_packet);
nisse284542b2017-01-10 08:58:32 -08002770 }
2771 });
2772}
2773
2774void Channel::SetTransportOverhead(size_t transport_overhead_per_packet) {
hbos3fd31fe2017-02-28 05:43:16 -08002775 rtc::CritScope cs(&overhead_per_packet_lock_);
nisse284542b2017-01-10 08:58:32 -08002776 transport_overhead_per_packet_ = transport_overhead_per_packet;
2777 UpdateOverheadForEncoder();
michaelt79e05882016-11-08 02:50:09 -08002778}
2779
hbos3fd31fe2017-02-28 05:43:16 -08002780// TODO(solenberg): Make AudioSendStream an OverheadObserver instead.
michaeltbf65be52016-12-15 06:24:49 -08002781void Channel::OnOverheadChanged(size_t overhead_bytes_per_packet) {
hbos3fd31fe2017-02-28 05:43:16 -08002782 rtc::CritScope cs(&overhead_per_packet_lock_);
nisse284542b2017-01-10 08:58:32 -08002783 rtp_overhead_per_packet_ = overhead_bytes_per_packet;
2784 UpdateOverheadForEncoder();
michaeltbf65be52016-12-15 06:24:49 -08002785}
2786
kwiberg55b97fe2016-01-28 05:22:45 -08002787int Channel::GetNetworkStatistics(NetworkStatistics& stats) {
2788 return audio_coding_->GetNetworkStatistics(&stats);
niklase@google.com470e71d2011-07-07 08:21:25 +00002789}
2790
wu@webrtc.org24301a62013-12-13 19:17:43 +00002791void Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const {
2792 audio_coding_->GetDecodingCallStatistics(stats);
2793}
2794
solenberg358057b2015-11-27 10:46:42 -08002795uint32_t Channel::GetDelayEstimate() const {
solenberg08b19df2017-02-15 00:42:31 -08002796 rtc::CritScope lock(&video_sync_lock_);
2797 return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_;
deadbeef74375882015-08-13 12:09:10 -07002798}
2799
kwiberg55b97fe2016-01-28 05:22:45 -08002800int Channel::SetMinimumPlayoutDelay(int delayMs) {
2801 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2802 "Channel::SetMinimumPlayoutDelay()");
2803 if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
2804 (delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) {
2805 _engineStatisticsPtr->SetLastError(
2806 VE_INVALID_ARGUMENT, kTraceError,
2807 "SetMinimumPlayoutDelay() invalid min delay");
2808 return -1;
2809 }
2810 if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) {
2811 _engineStatisticsPtr->SetLastError(
2812 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2813 "SetMinimumPlayoutDelay() failed to set min playout delay");
2814 return -1;
2815 }
2816 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002817}
2818
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002819int Channel::GetPlayoutTimestamp(unsigned int& timestamp) {
deadbeef74375882015-08-13 12:09:10 -07002820 uint32_t playout_timestamp_rtp = 0;
2821 {
tommi31fc21f2016-01-21 10:37:37 -08002822 rtc::CritScope lock(&video_sync_lock_);
deadbeef74375882015-08-13 12:09:10 -07002823 playout_timestamp_rtp = playout_timestamp_rtp_;
2824 }
kwiberg55b97fe2016-01-28 05:22:45 -08002825 if (playout_timestamp_rtp == 0) {
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002826 _engineStatisticsPtr->SetLastError(
skvlad4c0536b2016-07-07 13:06:26 -07002827 VE_CANNOT_RETRIEVE_VALUE, kTraceStateInfo,
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002828 "GetPlayoutTimestamp() failed to retrieve timestamp");
2829 return -1;
2830 }
deadbeef74375882015-08-13 12:09:10 -07002831 timestamp = playout_timestamp_rtp;
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002832 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002833}
2834
kwiberg55b97fe2016-01-28 05:22:45 -08002835int Channel::GetRtpRtcp(RtpRtcp** rtpRtcpModule,
2836 RtpReceiver** rtp_receiver) const {
2837 *rtpRtcpModule = _rtpRtcpModule.get();
2838 *rtp_receiver = rtp_receiver_.get();
2839 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002840}
2841
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00002842// TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
2843// a shared helper.
kwiberg55b97fe2016-01-28 05:22:45 -08002844int32_t Channel::MixOrReplaceAudioWithFile(int mixingFrequency) {
kwibergb7f89d62016-02-17 10:04:18 -08002845 std::unique_ptr<int16_t[]> fileBuffer(new int16_t[640]);
kwiberg55b97fe2016-01-28 05:22:45 -08002846 size_t fileSamples(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00002847
kwiberg55b97fe2016-01-28 05:22:45 -08002848 {
2849 rtc::CritScope cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002850
kwiberg5a25d952016-08-17 07:31:12 -07002851 if (!input_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002852 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2853 "Channel::MixOrReplaceAudioWithFile() fileplayer"
2854 " doesnt exist");
2855 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002856 }
2857
kwiberg4ec01d92016-08-22 08:43:54 -07002858 if (input_file_player_->Get10msAudioFromFile(fileBuffer.get(), &fileSamples,
kwiberg5a25d952016-08-17 07:31:12 -07002859 mixingFrequency) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08002860 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2861 "Channel::MixOrReplaceAudioWithFile() file mixing "
2862 "failed");
2863 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002864 }
kwiberg55b97fe2016-01-28 05:22:45 -08002865 if (fileSamples == 0) {
2866 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2867 "Channel::MixOrReplaceAudioWithFile() file is ended");
2868 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002869 }
kwiberg55b97fe2016-01-28 05:22:45 -08002870 }
2871
2872 assert(_audioFrame.samples_per_channel_ == fileSamples);
2873
2874 if (_mixFileWithMicrophone) {
2875 // Currently file stream is always mono.
2876 // TODO(xians): Change the code when FilePlayer supports real stereo.
2877 MixWithSat(_audioFrame.data_, _audioFrame.num_channels_, fileBuffer.get(),
2878 1, fileSamples);
2879 } else {
2880 // Replace ACM audio with file.
2881 // Currently file stream is always mono.
2882 // TODO(xians): Change the code when FilePlayer supports real stereo.
2883 _audioFrame.UpdateFrame(
2884 _channelId, 0xFFFFFFFF, fileBuffer.get(), fileSamples, mixingFrequency,
2885 AudioFrame::kNormalSpeech, AudioFrame::kVadUnknown, 1);
2886 }
2887 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002888}
2889
kwiberg55b97fe2016-01-28 05:22:45 -08002890int32_t Channel::MixAudioWithFile(AudioFrame& audioFrame, int mixingFrequency) {
2891 assert(mixingFrequency <= 48000);
niklase@google.com470e71d2011-07-07 08:21:25 +00002892
kwibergb7f89d62016-02-17 10:04:18 -08002893 std::unique_ptr<int16_t[]> fileBuffer(new int16_t[960]);
kwiberg55b97fe2016-01-28 05:22:45 -08002894 size_t fileSamples(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00002895
kwiberg55b97fe2016-01-28 05:22:45 -08002896 {
2897 rtc::CritScope cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002898
kwiberg5a25d952016-08-17 07:31:12 -07002899 if (!output_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002900 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2901 "Channel::MixAudioWithFile() file mixing failed");
2902 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002903 }
2904
kwiberg55b97fe2016-01-28 05:22:45 -08002905 // We should get the frequency we ask for.
kwiberg4ec01d92016-08-22 08:43:54 -07002906 if (output_file_player_->Get10msAudioFromFile(
2907 fileBuffer.get(), &fileSamples, mixingFrequency) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08002908 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2909 "Channel::MixAudioWithFile() file mixing failed");
2910 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002911 }
kwiberg55b97fe2016-01-28 05:22:45 -08002912 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002913
kwiberg55b97fe2016-01-28 05:22:45 -08002914 if (audioFrame.samples_per_channel_ == fileSamples) {
2915 // Currently file stream is always mono.
2916 // TODO(xians): Change the code when FilePlayer supports real stereo.
2917 MixWithSat(audioFrame.data_, audioFrame.num_channels_, fileBuffer.get(), 1,
2918 fileSamples);
2919 } else {
2920 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2921 "Channel::MixAudioWithFile() samples_per_channel_(%" PRIuS
2922 ") != "
2923 "fileSamples(%" PRIuS ")",
2924 audioFrame.samples_per_channel_, fileSamples);
2925 return -1;
2926 }
2927
2928 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002929}
2930
deadbeef74375882015-08-13 12:09:10 -07002931void Channel::UpdatePlayoutTimestamp(bool rtcp) {
henrik.lundin96bd5022016-04-06 04:13:56 -07002932 jitter_buffer_playout_timestamp_ = audio_coding_->PlayoutTimestamp();
deadbeef74375882015-08-13 12:09:10 -07002933
henrik.lundin96bd5022016-04-06 04:13:56 -07002934 if (!jitter_buffer_playout_timestamp_) {
2935 // This can happen if this channel has not received any RTP packets. In
2936 // this case, NetEq is not capable of computing a playout timestamp.
deadbeef74375882015-08-13 12:09:10 -07002937 return;
2938 }
2939
2940 uint16_t delay_ms = 0;
2941 if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08002942 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
deadbeef74375882015-08-13 12:09:10 -07002943 "Channel::UpdatePlayoutTimestamp() failed to read playout"
2944 " delay from the ADM");
2945 _engineStatisticsPtr->SetLastError(
2946 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
2947 "UpdatePlayoutTimestamp() failed to retrieve playout delay");
2948 return;
2949 }
2950
henrik.lundin96bd5022016-04-06 04:13:56 -07002951 RTC_DCHECK(jitter_buffer_playout_timestamp_);
2952 uint32_t playout_timestamp = *jitter_buffer_playout_timestamp_;
deadbeef74375882015-08-13 12:09:10 -07002953
2954 // Remove the playout delay.
ossue280cde2016-10-12 11:04:10 -07002955 playout_timestamp -= (delay_ms * (GetRtpTimestampRateHz() / 1000));
deadbeef74375882015-08-13 12:09:10 -07002956
kwiberg55b97fe2016-01-28 05:22:45 -08002957 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
deadbeef74375882015-08-13 12:09:10 -07002958 "Channel::UpdatePlayoutTimestamp() => playoutTimestamp = %lu",
henrik.lundin96bd5022016-04-06 04:13:56 -07002959 playout_timestamp);
deadbeef74375882015-08-13 12:09:10 -07002960
2961 {
tommi31fc21f2016-01-21 10:37:37 -08002962 rtc::CritScope lock(&video_sync_lock_);
solenberg81d93f32017-02-14 03:44:57 -08002963 if (!rtcp) {
henrik.lundin96bd5022016-04-06 04:13:56 -07002964 playout_timestamp_rtp_ = playout_timestamp;
deadbeef74375882015-08-13 12:09:10 -07002965 }
2966 playout_delay_ms_ = delay_ms;
2967 }
2968}
2969
kwiberg55b97fe2016-01-28 05:22:45 -08002970void Channel::RegisterReceiveCodecsToRTPModule() {
2971 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2972 "Channel::RegisterReceiveCodecsToRTPModule()");
niklase@google.com470e71d2011-07-07 08:21:25 +00002973
kwiberg55b97fe2016-01-28 05:22:45 -08002974 CodecInst codec;
2975 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
niklase@google.com470e71d2011-07-07 08:21:25 +00002976
kwiberg55b97fe2016-01-28 05:22:45 -08002977 for (int idx = 0; idx < nSupportedCodecs; idx++) {
2978 // Open up the RTP/RTCP receiver for all supported codecs
2979 if ((audio_coding_->Codec(idx, &codec) == -1) ||
magjed56124bd2016-11-24 09:34:46 -08002980 (rtp_receiver_->RegisterReceivePayload(codec) == -1)) {
kwiberg55b97fe2016-01-28 05:22:45 -08002981 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2982 "Channel::RegisterReceiveCodecsToRTPModule() unable"
2983 " to register %s (%d/%d/%" PRIuS
2984 "/%d) to RTP/RTCP "
2985 "receiver",
2986 codec.plname, codec.pltype, codec.plfreq, codec.channels,
2987 codec.rate);
2988 } else {
2989 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2990 "Channel::RegisterReceiveCodecsToRTPModule() %s "
2991 "(%d/%d/%" PRIuS
2992 "/%d) has been added to the RTP/RTCP "
2993 "receiver",
2994 codec.plname, codec.pltype, codec.plfreq, codec.channels,
2995 codec.rate);
niklase@google.com470e71d2011-07-07 08:21:25 +00002996 }
kwiberg55b97fe2016-01-28 05:22:45 -08002997 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002998}
2999
kwiberg55b97fe2016-01-28 05:22:45 -08003000int Channel::SetSendRtpHeaderExtension(bool enable,
3001 RTPExtensionType type,
wu@webrtc.orgebdb0e32014-03-06 23:49:08 +00003002 unsigned char id) {
3003 int error = 0;
3004 _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type);
3005 if (enable) {
3006 error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(type, id);
3007 }
3008 return error;
3009}
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00003010
ossue280cde2016-10-12 11:04:10 -07003011int Channel::GetRtpTimestampRateHz() const {
3012 const auto format = audio_coding_->ReceiveFormat();
3013 // Default to the playout frequency if we've not gotten any packets yet.
3014 // TODO(ossu): Zero clockrate can only happen if we've added an external
3015 // decoder for a format we don't support internally. Remove once that way of
3016 // adding decoders is gone!
3017 return (format && format->clockrate_hz != 0)
3018 ? format->clockrate_hz
3019 : audio_coding_->PlayoutFrequency();
wu@webrtc.org94454b72014-06-05 20:34:08 +00003020}
3021
Minyue2013aec2015-05-13 14:14:42 +02003022int64_t Channel::GetRTT(bool allow_associate_channel) const {
pbosda903ea2015-10-02 02:36:56 -07003023 RtcpMode method = _rtpRtcpModule->RTCP();
3024 if (method == RtcpMode::kOff) {
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003025 return 0;
3026 }
3027 std::vector<RTCPReportBlock> report_blocks;
3028 _rtpRtcpModule->RemoteRTCPStat(&report_blocks);
Minyue2013aec2015-05-13 14:14:42 +02003029
3030 int64_t rtt = 0;
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003031 if (report_blocks.empty()) {
Minyue2013aec2015-05-13 14:14:42 +02003032 if (allow_associate_channel) {
tommi31fc21f2016-01-21 10:37:37 -08003033 rtc::CritScope lock(&assoc_send_channel_lock_);
Minyue2013aec2015-05-13 14:14:42 +02003034 Channel* channel = associate_send_channel_.channel();
3035 // Tries to get RTT from an associated channel. This is important for
3036 // receive-only channels.
3037 if (channel) {
3038 // To prevent infinite recursion and deadlock, calling GetRTT of
3039 // associate channel should always use "false" for argument:
3040 // |allow_associate_channel|.
3041 rtt = channel->GetRTT(false);
3042 }
3043 }
3044 return rtt;
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003045 }
3046
3047 uint32_t remoteSSRC = rtp_receiver_->SSRC();
3048 std::vector<RTCPReportBlock>::const_iterator it = report_blocks.begin();
3049 for (; it != report_blocks.end(); ++it) {
3050 if (it->remoteSSRC == remoteSSRC)
3051 break;
3052 }
3053 if (it == report_blocks.end()) {
3054 // We have not received packets with SSRC matching the report blocks.
3055 // To calculate RTT we try with the SSRC of the first report block.
3056 // This is very important for send-only channels where we don't know
3057 // the SSRC of the other end.
3058 remoteSSRC = report_blocks[0].remoteSSRC;
3059 }
Minyue2013aec2015-05-13 14:14:42 +02003060
pkasting@chromium.org16825b12015-01-12 21:51:21 +00003061 int64_t avg_rtt = 0;
kwiberg55b97fe2016-01-28 05:22:45 -08003062 int64_t max_rtt = 0;
pkasting@chromium.org16825b12015-01-12 21:51:21 +00003063 int64_t min_rtt = 0;
kwiberg55b97fe2016-01-28 05:22:45 -08003064 if (_rtpRtcpModule->RTT(remoteSSRC, &rtt, &avg_rtt, &min_rtt, &max_rtt) !=
3065 0) {
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003066 return 0;
3067 }
pkasting@chromium.org16825b12015-01-12 21:51:21 +00003068 return rtt;
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003069}
3070
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00003071} // namespace voe
3072} // namespace webrtc