Line data Source code
1 : /*
2 : * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/voice_engine/channel.h"
12 :
13 : #include <algorithm>
14 : #include <utility>
15 :
16 : #include "webrtc/audio/utility/audio_frame_operations.h"
17 : #include "webrtc/base/array_view.h"
18 : #include "webrtc/base/checks.h"
19 : #include "webrtc/base/criticalsection.h"
20 : #include "webrtc/base/format_macros.h"
21 : #include "webrtc/base/logging.h"
22 : #include "webrtc/base/rate_limiter.h"
23 : #include "webrtc/base/thread_checker.h"
24 : #include "webrtc/base/timeutils.h"
25 : #include "webrtc/config.h"
26 : #include "webrtc/logging/rtc_event_log/rtc_event_log.h"
27 : #include "webrtc/modules/audio_coding/codecs/audio_format_conversion.h"
28 : #include "webrtc/modules/audio_device/include/audio_device.h"
29 : #include "webrtc/modules/audio_processing/include/audio_processing.h"
30 : #include "webrtc/modules/include/module_common_types.h"
31 : #include "webrtc/modules/pacing/packet_router.h"
32 : #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"
35 : #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
36 : #include "webrtc/modules/utility/include/process_thread.h"
37 : #include "webrtc/system_wrappers/include/trace.h"
38 : #include "webrtc/voice_engine/include/voe_external_media.h"
39 : #include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
40 : #include "webrtc/voice_engine/output_mixer.h"
41 : #include "webrtc/voice_engine/statistics.h"
42 : #include "webrtc/voice_engine/transmit_mixer.h"
43 : #include "webrtc/voice_engine/utility.h"
44 :
45 : namespace webrtc {
46 : namespace voe {
47 :
48 : namespace {
49 :
50 : constexpr int64_t kMaxRetransmissionWindowMs = 1000;
51 : constexpr int64_t kMinRetransmissionWindowMs = 30;
52 :
53 : } // namespace
54 :
55 : const int kTelephoneEventAttenuationdB = 10;
56 :
57 0 : class RtcEventLogProxy final : public webrtc::RtcEventLog {
58 : public:
59 0 : RtcEventLogProxy() : event_log_(nullptr) {}
60 :
61 0 : bool StartLogging(const std::string& file_name,
62 : int64_t max_size_bytes) override {
63 0 : RTC_NOTREACHED();
64 0 : return false;
65 : }
66 :
67 0 : bool StartLogging(rtc::PlatformFile log_file,
68 : int64_t max_size_bytes) override {
69 0 : RTC_NOTREACHED();
70 0 : return false;
71 : }
72 :
73 0 : void StopLogging() override { RTC_NOTREACHED(); }
74 :
75 0 : void LogVideoReceiveStreamConfig(
76 : const webrtc::VideoReceiveStream::Config& config) override {
77 0 : rtc::CritScope lock(&crit_);
78 0 : if (event_log_) {
79 0 : event_log_->LogVideoReceiveStreamConfig(config);
80 : }
81 0 : }
82 :
83 0 : void LogVideoSendStreamConfig(
84 : const webrtc::VideoSendStream::Config& config) override {
85 0 : rtc::CritScope lock(&crit_);
86 0 : if (event_log_) {
87 0 : event_log_->LogVideoSendStreamConfig(config);
88 : }
89 0 : }
90 :
91 0 : void LogAudioReceiveStreamConfig(
92 : const webrtc::AudioReceiveStream::Config& config) override {
93 0 : rtc::CritScope lock(&crit_);
94 0 : if (event_log_) {
95 0 : event_log_->LogAudioReceiveStreamConfig(config);
96 : }
97 0 : }
98 :
99 0 : void LogAudioSendStreamConfig(
100 : const webrtc::AudioSendStream::Config& config) override {
101 0 : rtc::CritScope lock(&crit_);
102 0 : if (event_log_) {
103 0 : event_log_->LogAudioSendStreamConfig(config);
104 : }
105 0 : }
106 :
107 0 : void LogRtpHeader(webrtc::PacketDirection direction,
108 : webrtc::MediaType media_type,
109 : const uint8_t* header,
110 : size_t packet_length) override {
111 0 : rtc::CritScope lock(&crit_);
112 0 : if (event_log_) {
113 0 : event_log_->LogRtpHeader(direction, media_type, header, packet_length);
114 : }
115 0 : }
116 :
117 0 : void LogRtcpPacket(webrtc::PacketDirection direction,
118 : webrtc::MediaType media_type,
119 : const uint8_t* packet,
120 : size_t length) override {
121 0 : rtc::CritScope lock(&crit_);
122 0 : if (event_log_) {
123 0 : event_log_->LogRtcpPacket(direction, media_type, packet, length);
124 : }
125 0 : }
126 :
127 0 : void LogAudioPlayout(uint32_t ssrc) override {
128 0 : rtc::CritScope lock(&crit_);
129 0 : if (event_log_) {
130 0 : event_log_->LogAudioPlayout(ssrc);
131 : }
132 0 : }
133 :
134 0 : void LogBwePacketLossEvent(int32_t bitrate,
135 : uint8_t fraction_loss,
136 : int32_t total_packets) override {
137 0 : rtc::CritScope lock(&crit_);
138 0 : if (event_log_) {
139 0 : event_log_->LogBwePacketLossEvent(bitrate, fraction_loss, total_packets);
140 : }
141 0 : }
142 :
143 0 : void SetEventLog(RtcEventLog* event_log) {
144 0 : rtc::CritScope lock(&crit_);
145 0 : event_log_ = event_log;
146 0 : }
147 :
148 : private:
149 : rtc::CriticalSection crit_;
150 : RtcEventLog* event_log_ GUARDED_BY(crit_);
151 : RTC_DISALLOW_COPY_AND_ASSIGN(RtcEventLogProxy);
152 : };
153 :
154 0 : class RtcpRttStatsProxy final : public RtcpRttStats {
155 : public:
156 0 : RtcpRttStatsProxy() : rtcp_rtt_stats_(nullptr) {}
157 :
158 0 : void OnRttUpdate(int64_t rtt) override {
159 0 : rtc::CritScope lock(&crit_);
160 0 : if (rtcp_rtt_stats_)
161 0 : rtcp_rtt_stats_->OnRttUpdate(rtt);
162 0 : }
163 :
164 0 : int64_t LastProcessedRtt() const override {
165 0 : rtc::CritScope lock(&crit_);
166 0 : if (!rtcp_rtt_stats_)
167 0 : return 0;
168 0 : return rtcp_rtt_stats_->LastProcessedRtt();
169 : }
170 :
171 0 : void SetRtcpRttStats(RtcpRttStats* rtcp_rtt_stats) {
172 0 : rtc::CritScope lock(&crit_);
173 0 : rtcp_rtt_stats_ = rtcp_rtt_stats;
174 0 : }
175 :
176 : private:
177 : rtc::CriticalSection crit_;
178 : RtcpRttStats* rtcp_rtt_stats_ GUARDED_BY(crit_);
179 : RTC_DISALLOW_COPY_AND_ASSIGN(RtcpRttStatsProxy);
180 : };
181 :
182 0 : class TransportFeedbackProxy : public TransportFeedbackObserver {
183 : public:
184 0 : TransportFeedbackProxy() : feedback_observer_(nullptr) {
185 0 : pacer_thread_.DetachFromThread();
186 0 : network_thread_.DetachFromThread();
187 0 : }
188 :
189 0 : void SetTransportFeedbackObserver(
190 : TransportFeedbackObserver* feedback_observer) {
191 0 : RTC_DCHECK(thread_checker_.CalledOnValidThread());
192 0 : rtc::CritScope lock(&crit_);
193 0 : feedback_observer_ = feedback_observer;
194 0 : }
195 :
196 : // Implements TransportFeedbackObserver.
197 0 : void AddPacket(uint16_t sequence_number,
198 : size_t length,
199 : int probe_cluster_id) override {
200 0 : RTC_DCHECK(pacer_thread_.CalledOnValidThread());
201 0 : rtc::CritScope lock(&crit_);
202 0 : if (feedback_observer_)
203 0 : feedback_observer_->AddPacket(sequence_number, length, probe_cluster_id);
204 0 : }
205 0 : void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override {
206 0 : RTC_DCHECK(network_thread_.CalledOnValidThread());
207 0 : rtc::CritScope lock(&crit_);
208 0 : if (feedback_observer_)
209 0 : feedback_observer_->OnTransportFeedback(feedback);
210 0 : }
211 0 : std::vector<PacketInfo> GetTransportFeedbackVector() const override {
212 0 : RTC_NOTREACHED();
213 0 : return std::vector<PacketInfo>();
214 : }
215 :
216 : private:
217 : rtc::CriticalSection crit_;
218 : rtc::ThreadChecker thread_checker_;
219 : rtc::ThreadChecker pacer_thread_;
220 : rtc::ThreadChecker network_thread_;
221 : TransportFeedbackObserver* feedback_observer_ GUARDED_BY(&crit_);
222 : };
223 :
224 0 : class TransportSequenceNumberProxy : public TransportSequenceNumberAllocator {
225 : public:
226 0 : TransportSequenceNumberProxy() : seq_num_allocator_(nullptr) {
227 0 : pacer_thread_.DetachFromThread();
228 0 : }
229 :
230 0 : void SetSequenceNumberAllocator(
231 : TransportSequenceNumberAllocator* seq_num_allocator) {
232 0 : RTC_DCHECK(thread_checker_.CalledOnValidThread());
233 0 : rtc::CritScope lock(&crit_);
234 0 : seq_num_allocator_ = seq_num_allocator;
235 0 : }
236 :
237 : // Implements TransportSequenceNumberAllocator.
238 0 : uint16_t AllocateSequenceNumber() override {
239 0 : RTC_DCHECK(pacer_thread_.CalledOnValidThread());
240 0 : rtc::CritScope lock(&crit_);
241 0 : if (!seq_num_allocator_)
242 0 : return 0;
243 0 : return seq_num_allocator_->AllocateSequenceNumber();
244 : }
245 :
246 : private:
247 : rtc::CriticalSection crit_;
248 : rtc::ThreadChecker thread_checker_;
249 : rtc::ThreadChecker pacer_thread_;
250 : TransportSequenceNumberAllocator* seq_num_allocator_ GUARDED_BY(&crit_);
251 : };
252 :
253 0 : class RtpPacketSenderProxy : public RtpPacketSender {
254 : public:
255 0 : RtpPacketSenderProxy() : rtp_packet_sender_(nullptr) {}
256 :
257 0 : void SetPacketSender(RtpPacketSender* rtp_packet_sender) {
258 0 : RTC_DCHECK(thread_checker_.CalledOnValidThread());
259 0 : rtc::CritScope lock(&crit_);
260 0 : rtp_packet_sender_ = rtp_packet_sender;
261 0 : }
262 :
263 : // Implements RtpPacketSender.
264 0 : void InsertPacket(Priority priority,
265 : uint32_t ssrc,
266 : uint16_t sequence_number,
267 : int64_t capture_time_ms,
268 : size_t bytes,
269 : bool retransmission) override {
270 0 : rtc::CritScope lock(&crit_);
271 0 : if (rtp_packet_sender_) {
272 0 : rtp_packet_sender_->InsertPacket(priority, ssrc, sequence_number,
273 0 : capture_time_ms, bytes, retransmission);
274 : }
275 0 : }
276 :
277 : private:
278 : rtc::ThreadChecker thread_checker_;
279 : rtc::CriticalSection crit_;
280 : RtpPacketSender* rtp_packet_sender_ GUARDED_BY(&crit_);
281 : };
282 :
283 : // Extend the default RTCP statistics struct with max_jitter, defined as the
284 : // maximum jitter value seen in an RTCP report block.
285 : struct ChannelStatistics : public RtcpStatistics {
286 0 : ChannelStatistics() : rtcp(), max_jitter(0) {}
287 :
288 : RtcpStatistics rtcp;
289 : uint32_t max_jitter;
290 : };
291 :
292 : // Statistics callback, called at each generation of a new RTCP report block.
293 : class StatisticsProxy : public RtcpStatisticsCallback,
294 : public RtcpPacketTypeCounterObserver {
295 : public:
296 0 : StatisticsProxy(uint32_t ssrc) : ssrc_(ssrc) {}
297 0 : virtual ~StatisticsProxy() {}
298 :
299 0 : void StatisticsUpdated(const RtcpStatistics& statistics,
300 : uint32_t ssrc) override {
301 0 : rtc::CritScope cs(&stats_lock_);
302 0 : if (ssrc != ssrc_)
303 0 : return;
304 :
305 0 : stats_.rtcp = statistics;
306 0 : if (statistics.jitter > stats_.max_jitter) {
307 0 : stats_.max_jitter = statistics.jitter;
308 : }
309 : }
310 :
311 0 : void CNameChanged(const char* cname, uint32_t ssrc) override {}
312 :
313 0 : void SetSSRC(uint32_t ssrc) {
314 0 : rtc::CritScope cs(&stats_lock_);
315 0 : ssrc_ = ssrc;
316 0 : }
317 :
318 0 : ChannelStatistics GetStats() {
319 0 : rtc::CritScope cs(&stats_lock_);
320 0 : return stats_;
321 : }
322 :
323 0 : void RtcpPacketTypesCounterUpdated(uint32_t ssrc,
324 : const RtcpPacketTypeCounter& packet_counter) override {
325 0 : rtc::CritScope cs(&stats_lock_);
326 0 : if (ssrc != ssrc_) {
327 0 : return;
328 : }
329 0 : packet_counter_ = packet_counter;
330 : };
331 :
332 0 : void GetPacketTypeCounter(RtcpPacketTypeCounter& aPacketTypeCounter) {
333 0 : rtc::CritScope cs(&stats_lock_);
334 0 : aPacketTypeCounter = packet_counter_;
335 0 : }
336 :
337 : private:
338 : // StatisticsUpdated calls are triggered from threads in the RTP module,
339 : // while GetStats calls can be triggered from the public voice engine API,
340 : // hence synchronization is needed.
341 : rtc::CriticalSection stats_lock_;
342 : uint32_t ssrc_;
343 : ChannelStatistics stats_;
344 : RtcpPacketTypeCounter packet_counter_;
345 : };
346 :
347 : class VoERtcpObserver : public RtcpBandwidthObserver {
348 : public:
349 0 : explicit VoERtcpObserver(Channel* owner) : owner_(owner) {}
350 0 : virtual ~VoERtcpObserver() {}
351 :
352 0 : void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
353 : // Not used for Voice Engine.
354 0 : }
355 :
356 0 : void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
357 : int64_t rtt,
358 : int64_t now_ms) override {
359 : // TODO(mflodman): Do we need to aggregate reports here or can we jut send
360 : // what we get? I.e. do we ever get multiple reports bundled into one RTCP
361 : // report for VoiceEngine?
362 0 : if (report_blocks.empty())
363 0 : return;
364 :
365 0 : int fraction_lost_aggregate = 0;
366 0 : int total_number_of_packets = 0;
367 :
368 : // If receiving multiple report blocks, calculate the weighted average based
369 : // on the number of packets a report refers to.
370 0 : for (ReportBlockList::const_iterator block_it = report_blocks.begin();
371 0 : block_it != report_blocks.end(); ++block_it) {
372 : // Find the previous extended high sequence number for this remote SSRC,
373 : // to calculate the number of RTP packets this report refers to. Ignore if
374 : // we haven't seen this SSRC before.
375 : std::map<uint32_t, uint32_t>::iterator seq_num_it =
376 0 : extended_max_sequence_number_.find(block_it->sourceSSRC);
377 0 : int number_of_packets = 0;
378 0 : if (seq_num_it != extended_max_sequence_number_.end()) {
379 0 : number_of_packets = block_it->extendedHighSeqNum - seq_num_it->second;
380 : }
381 0 : fraction_lost_aggregate += number_of_packets * block_it->fractionLost;
382 0 : total_number_of_packets += number_of_packets;
383 :
384 0 : extended_max_sequence_number_[block_it->sourceSSRC] =
385 0 : block_it->extendedHighSeqNum;
386 : }
387 0 : int weighted_fraction_lost = 0;
388 0 : if (total_number_of_packets > 0) {
389 0 : weighted_fraction_lost =
390 0 : (fraction_lost_aggregate + total_number_of_packets / 2) /
391 : total_number_of_packets;
392 : }
393 0 : owner_->OnIncomingFractionLoss(weighted_fraction_lost);
394 : }
395 :
396 : private:
397 : Channel* owner_;
398 : // Maps remote side ssrc to extended highest sequence number received.
399 : std::map<uint32_t, uint32_t> extended_max_sequence_number_;
400 : };
401 :
402 0 : int32_t Channel::SendData(FrameType frameType,
403 : uint8_t payloadType,
404 : uint32_t timeStamp,
405 : const uint8_t* payloadData,
406 : size_t payloadSize,
407 : const RTPFragmentationHeader* fragmentation) {
408 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
409 : "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u,"
410 : " payloadSize=%" PRIuS ", fragmentation=0x%x)",
411 : frameType, payloadType, timeStamp, payloadSize, fragmentation);
412 :
413 0 : if (_includeAudioLevelIndication) {
414 : // Store current audio level in the RTP/RTCP module.
415 : // The level will be used in combination with voice-activity state
416 : // (frameType) to add an RTP header extension
417 0 : _rtpRtcpModule->SetAudioLevel(rms_level_.Average());
418 : }
419 :
420 : // Push data from ACM to RTP/RTCP-module to deliver audio frame for
421 : // packetization.
422 : // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
423 0 : if (!_rtpRtcpModule->SendOutgoingData(
424 : (FrameType&)frameType, payloadType, timeStamp,
425 : // Leaving the time when this frame was
426 : // received from the capture device as
427 : // undefined for voice for now.
428 0 : -1, payloadData, payloadSize, fragmentation, nullptr, nullptr)) {
429 0 : _engineStatisticsPtr->SetLastError(
430 : VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
431 0 : "Channel::SendData() failed to send data to RTP/RTCP module");
432 0 : return -1;
433 : }
434 :
435 0 : _lastLocalTimeStamp = timeStamp;
436 0 : _lastPayloadType = payloadType;
437 :
438 0 : return 0;
439 : }
440 :
441 0 : int32_t Channel::InFrameType(FrameType frame_type) {
442 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
443 : "Channel::InFrameType(frame_type=%d)", frame_type);
444 :
445 0 : rtc::CritScope cs(&_callbackCritSect);
446 0 : _sendFrameType = (frame_type == kAudioFrameSpeech);
447 0 : return 0;
448 : }
449 :
450 0 : bool Channel::SendRtp(const uint8_t* data,
451 : size_t len,
452 : const PacketOptions& options) {
453 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
454 : "Channel::SendPacket(channel=%d, len=%" PRIuS ")", len);
455 :
456 0 : rtc::CritScope cs(&_callbackCritSect);
457 :
458 0 : if (_transportPtr == NULL) {
459 : WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
460 : "Channel::SendPacket() failed to send RTP packet due to"
461 : " invalid transport object");
462 0 : return false;
463 : }
464 :
465 0 : uint8_t* bufferToSendPtr = (uint8_t*)data;
466 0 : size_t bufferLength = len;
467 :
468 0 : if (!_transportPtr->SendRtp(bufferToSendPtr, bufferLength, options)) {
469 : std::string transport_name =
470 0 : _externalTransport ? "external transport" : "WebRtc sockets";
471 : WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
472 : "Channel::SendPacket() RTP transmission using %s failed",
473 : transport_name.c_str());
474 0 : return false;
475 : }
476 0 : return true;
477 : }
478 :
479 0 : bool Channel::SendRtcp(const uint8_t* data, size_t len) {
480 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
481 : "Channel::SendRtcp(len=%" PRIuS ")", len);
482 :
483 0 : rtc::CritScope cs(&_callbackCritSect);
484 0 : if (_transportPtr == NULL) {
485 : WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
486 : "Channel::SendRtcp() failed to send RTCP packet"
487 : " due to invalid transport object");
488 0 : return false;
489 : }
490 :
491 0 : uint8_t* bufferToSendPtr = (uint8_t*)data;
492 0 : size_t bufferLength = len;
493 :
494 0 : int n = _transportPtr->SendRtcp(bufferToSendPtr, bufferLength);
495 0 : if (n < 0) {
496 : std::string transport_name =
497 0 : _externalTransport ? "external transport" : "WebRtc sockets";
498 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
499 : "Channel::SendRtcp() transmission using %s failed",
500 : transport_name.c_str());
501 0 : return false;
502 : }
503 0 : return true;
504 : }
505 :
506 0 : void Channel::OnIncomingSSRCChanged(uint32_t ssrc) {
507 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
508 : "Channel::OnIncomingSSRCChanged(SSRC=%d)", ssrc);
509 :
510 : // Update ssrc so that NTP for AV sync can be updated.
511 0 : _rtpRtcpModule->SetRemoteSSRC(ssrc);
512 : // Update stats proxy to receive stats for new ssrc
513 0 : statistics_proxy_->SetSSRC(ssrc);
514 0 : }
515 :
516 0 : void Channel::OnIncomingCSRCChanged(uint32_t CSRC, bool added) {
517 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
518 : "Channel::OnIncomingCSRCChanged(CSRC=%d, added=%d)", CSRC,
519 : added);
520 0 : }
521 :
522 0 : int32_t Channel::OnInitializeDecoder(
523 : int8_t payloadType,
524 : const char payloadName[RTP_PAYLOAD_NAME_SIZE],
525 : int frequency,
526 : size_t channels,
527 : uint32_t rate) {
528 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
529 : "Channel::OnInitializeDecoder(payloadType=%d, "
530 : "payloadName=%s, frequency=%u, channels=%" PRIuS ", rate=%u)",
531 : payloadType, payloadName, frequency, channels, rate);
532 :
533 0 : CodecInst receiveCodec = {0};
534 0 : CodecInst dummyCodec = {0};
535 :
536 0 : receiveCodec.pltype = payloadType;
537 0 : receiveCodec.plfreq = frequency;
538 0 : receiveCodec.channels = channels;
539 0 : receiveCodec.rate = rate;
540 0 : strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
541 :
542 0 : audio_coding_->Codec(payloadName, &dummyCodec, frequency, channels);
543 0 : receiveCodec.pacsize = dummyCodec.pacsize;
544 :
545 : // Register the new codec to the ACM
546 0 : if (!audio_coding_->RegisterReceiveCodec(receiveCodec.pltype,
547 0 : CodecInstToSdp(receiveCodec))) {
548 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
549 : "Channel::OnInitializeDecoder() invalid codec ("
550 : "pt=%d, name=%s) received - 1",
551 : payloadType, payloadName);
552 0 : _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR);
553 0 : return -1;
554 : }
555 :
556 0 : return 0;
557 : }
558 :
559 0 : int32_t Channel::OnReceivedPayloadData(const uint8_t* payloadData,
560 : size_t payloadSize,
561 : const WebRtcRTPHeader* rtpHeader) {
562 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
563 : "Channel::OnReceivedPayloadData(payloadSize=%" PRIuS
564 : ","
565 : " payloadType=%u, audioChannel=%" PRIuS ")",
566 : payloadSize, rtpHeader->header.payloadType,
567 : rtpHeader->type.Audio.channel);
568 :
569 0 : if (!channel_state_.Get().playing) {
570 : // Avoid inserting into NetEQ when we are not playing. Count the
571 : // packet as discarded.
572 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
573 : "received packet is discarded since playing is not"
574 : " activated");
575 0 : _numberOfDiscardedPackets++;
576 0 : return 0;
577 : }
578 :
579 : // Push the incoming payload (parsed and ready for decoding) into the ACM
580 0 : if (audio_coding_->IncomingPacket(payloadData, payloadSize, *rtpHeader) !=
581 : 0) {
582 0 : _engineStatisticsPtr->SetLastError(
583 : VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
584 0 : "Channel::OnReceivedPayloadData() unable to push data to the ACM");
585 0 : return -1;
586 : }
587 :
588 0 : int64_t round_trip_time = 0;
589 0 : _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), &round_trip_time, NULL, NULL,
590 0 : NULL);
591 :
592 0 : std::vector<uint16_t> nack_list = audio_coding_->GetNackList(round_trip_time);
593 0 : if (!nack_list.empty()) {
594 : // Can't use nack_list.data() since it's not supported by all
595 : // compilers.
596 0 : ResendPackets(&(nack_list[0]), static_cast<int>(nack_list.size()));
597 : }
598 0 : return 0;
599 : }
600 :
601 0 : bool Channel::OnRecoveredPacket(const uint8_t* rtp_packet,
602 : size_t rtp_packet_length) {
603 0 : RTPHeader header;
604 0 : if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
605 : WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVoice, _channelId,
606 : "IncomingPacket invalid RTP header");
607 0 : return false;
608 : }
609 0 : header.payload_type_frequency =
610 0 : rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
611 0 : if (header.payload_type_frequency < 0)
612 0 : return false;
613 0 : return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
614 : }
615 :
616 0 : MixerParticipant::AudioFrameInfo Channel::GetAudioFrameWithMuted(
617 : int32_t id,
618 : AudioFrame* audioFrame) {
619 : unsigned int ssrc;
620 0 : RTC_CHECK_EQ(GetLocalSSRC(ssrc), 0);
621 0 : event_log_proxy_->LogAudioPlayout(ssrc);
622 : // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
623 : bool muted;
624 0 : if (audio_coding_->PlayoutData10Ms(audioFrame->sample_rate_hz_, audioFrame,
625 0 : &muted) == -1) {
626 : WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
627 : "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
628 : // In all likelihood, the audio in this frame is garbage. We return an
629 : // error so that the audio mixer module doesn't add it to the mix. As
630 : // a result, it won't be played out and the actions skipped here are
631 : // irrelevant.
632 0 : return MixerParticipant::AudioFrameInfo::kError;
633 : }
634 :
635 0 : if (muted) {
636 : // TODO(henrik.lundin): We should be able to do better than this. But we
637 : // will have to go through all the cases below where the audio samples may
638 : // be used, and handle the muted case in some way.
639 0 : AudioFrameOperations::Mute(audioFrame);
640 : }
641 :
642 : // Convert module ID to internal VoE channel ID
643 0 : audioFrame->id_ = VoEChannelId(audioFrame->id_);
644 : // Store speech type for dead-or-alive detection
645 0 : _outputSpeechType = audioFrame->speech_type_;
646 :
647 0 : ChannelState::State state = channel_state_.Get();
648 :
649 : {
650 : // Pass the audio buffers to an optional sink callback, before applying
651 : // scaling/panning, as that applies to the mix operation.
652 : // External recipients of the audio (e.g. via AudioTrack), will do their
653 : // own mixing/dynamic processing.
654 0 : rtc::CritScope cs(&_callbackCritSect);
655 0 : if (audio_sink_) {
656 : AudioSinkInterface::Data data(
657 : &audioFrame->data_[0], audioFrame->samples_per_channel_,
658 : audioFrame->sample_rate_hz_, audioFrame->num_channels_,
659 0 : audioFrame->timestamp_);
660 0 : audio_sink_->OnData(data);
661 : }
662 : }
663 :
664 0 : float output_gain = 1.0f;
665 0 : float left_pan = 1.0f;
666 0 : float right_pan = 1.0f;
667 : {
668 0 : rtc::CritScope cs(&volume_settings_critsect_);
669 0 : output_gain = _outputGain;
670 0 : left_pan = _panLeft;
671 0 : right_pan = _panRight;
672 : }
673 :
674 : // Output volume scaling
675 0 : if (output_gain < 0.99f || output_gain > 1.01f) {
676 0 : AudioFrameOperations::ScaleWithSat(output_gain, *audioFrame);
677 : }
678 :
679 : // Scale left and/or right channel(s) if stereo and master balance is
680 : // active
681 :
682 0 : if (left_pan != 1.0f || right_pan != 1.0f) {
683 0 : if (audioFrame->num_channels_ == 1) {
684 : // Emulate stereo mode since panning is active.
685 : // The mono signal is copied to both left and right channels here.
686 0 : AudioFrameOperations::MonoToStereo(audioFrame);
687 : }
688 : // For true stereo mode (when we are receiving a stereo signal), no
689 : // action is needed.
690 :
691 : // Do the panning operation (the audio frame contains stereo at this
692 : // stage)
693 0 : AudioFrameOperations::Scale(left_pan, right_pan, *audioFrame);
694 : }
695 :
696 : // Mix decoded PCM output with file if file mixing is enabled
697 0 : if (state.output_file_playing) {
698 0 : MixAudioWithFile(*audioFrame, audioFrame->sample_rate_hz_);
699 0 : muted = false; // We may have added non-zero samples.
700 : }
701 :
702 : // External media
703 0 : if (_outputExternalMedia) {
704 0 : rtc::CritScope cs(&_callbackCritSect);
705 0 : const bool isStereo = (audioFrame->num_channels_ == 2);
706 0 : if (_outputExternalMediaCallbackPtr) {
707 0 : _outputExternalMediaCallbackPtr->Process(
708 : _channelId, kPlaybackPerChannel, (int16_t*)audioFrame->data_,
709 : audioFrame->samples_per_channel_, audioFrame->sample_rate_hz_,
710 0 : isStereo);
711 : }
712 : }
713 :
714 : // Record playout if enabled
715 : {
716 0 : rtc::CritScope cs(&_fileCritSect);
717 :
718 0 : if (_outputFileRecording && output_file_recorder_) {
719 0 : output_file_recorder_->RecordAudioToFile(*audioFrame);
720 : }
721 : }
722 :
723 : // Measure audio level (0-9)
724 : // TODO(henrik.lundin) Use the |muted| information here too.
725 0 : _outputAudioLevel.ComputeLevel(*audioFrame);
726 :
727 0 : if (capture_start_rtp_time_stamp_ < 0 && audioFrame->timestamp_ != 0) {
728 : // The first frame with a valid rtp timestamp.
729 0 : capture_start_rtp_time_stamp_ = audioFrame->timestamp_;
730 : }
731 :
732 0 : if (capture_start_rtp_time_stamp_ >= 0) {
733 : // audioFrame.timestamp_ should be valid from now on.
734 :
735 : // Compute elapsed time.
736 : int64_t unwrap_timestamp =
737 0 : rtp_ts_wraparound_handler_->Unwrap(audioFrame->timestamp_);
738 0 : audioFrame->elapsed_time_ms_ =
739 0 : (unwrap_timestamp - capture_start_rtp_time_stamp_) /
740 0 : (GetRtpTimestampRateHz() / 1000);
741 :
742 : {
743 0 : rtc::CritScope lock(&ts_stats_lock_);
744 : // Compute ntp time.
745 0 : audioFrame->ntp_time_ms_ =
746 0 : ntp_estimator_.Estimate(audioFrame->timestamp_);
747 : // |ntp_time_ms_| won't be valid until at least 2 RTCP SRs are received.
748 0 : if (audioFrame->ntp_time_ms_ > 0) {
749 : // Compute |capture_start_ntp_time_ms_| so that
750 : // |capture_start_ntp_time_ms_| + |elapsed_time_ms_| == |ntp_time_ms_|
751 0 : capture_start_ntp_time_ms_ =
752 0 : audioFrame->ntp_time_ms_ - audioFrame->elapsed_time_ms_;
753 : }
754 : }
755 : }
756 :
757 0 : return muted ? MixerParticipant::AudioFrameInfo::kMuted
758 0 : : MixerParticipant::AudioFrameInfo::kNormal;
759 : }
760 :
761 0 : AudioMixer::Source::AudioFrameInfo Channel::GetAudioFrameWithInfo(
762 : int sample_rate_hz,
763 : AudioFrame* audio_frame) {
764 0 : audio_frame->sample_rate_hz_ = sample_rate_hz;
765 :
766 0 : const auto frame_info = GetAudioFrameWithMuted(-1, audio_frame);
767 :
768 : using FrameInfo = AudioMixer::Source::AudioFrameInfo;
769 0 : FrameInfo new_audio_frame_info = FrameInfo::kError;
770 0 : switch (frame_info) {
771 : case MixerParticipant::AudioFrameInfo::kNormal:
772 0 : new_audio_frame_info = FrameInfo::kNormal;
773 0 : break;
774 : case MixerParticipant::AudioFrameInfo::kMuted:
775 0 : new_audio_frame_info = FrameInfo::kMuted;
776 0 : break;
777 : case MixerParticipant::AudioFrameInfo::kError:
778 0 : new_audio_frame_info = FrameInfo::kError;
779 0 : break;
780 : }
781 0 : return new_audio_frame_info;
782 : }
783 :
784 0 : int32_t Channel::NeededFrequency(int32_t id) const {
785 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
786 : "Channel::NeededFrequency(id=%d)", id);
787 :
788 0 : int highestNeeded = 0;
789 :
790 : // Determine highest needed receive frequency
791 0 : int32_t receiveFrequency = audio_coding_->ReceiveFrequency();
792 :
793 : // Return the bigger of playout and receive frequency in the ACM.
794 0 : if (audio_coding_->PlayoutFrequency() > receiveFrequency) {
795 0 : highestNeeded = audio_coding_->PlayoutFrequency();
796 : } else {
797 0 : highestNeeded = receiveFrequency;
798 : }
799 :
800 : // Special case, if we're playing a file on the playout side
801 : // we take that frequency into consideration as well
802 : // This is not needed on sending side, since the codec will
803 : // limit the spectrum anyway.
804 0 : if (channel_state_.Get().output_file_playing) {
805 0 : rtc::CritScope cs(&_fileCritSect);
806 0 : if (output_file_player_) {
807 0 : if (output_file_player_->Frequency() > highestNeeded) {
808 0 : highestNeeded = output_file_player_->Frequency();
809 : }
810 : }
811 : }
812 :
813 0 : return (highestNeeded);
814 : }
815 :
816 0 : int32_t Channel::CreateChannel(
817 : Channel*& channel,
818 : int32_t channelId,
819 : uint32_t instanceId,
820 : const VoEBase::ChannelConfig& config) {
821 : WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId, channelId),
822 : "Channel::CreateChannel(channelId=%d, instanceId=%d)", channelId,
823 : instanceId);
824 :
825 0 : channel = new Channel(channelId, instanceId, config);
826 0 : if (channel == NULL) {
827 : WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId, channelId),
828 : "Channel::CreateChannel() unable to allocate memory for"
829 : " channel");
830 0 : return -1;
831 : }
832 0 : return 0;
833 : }
834 :
835 0 : void Channel::PlayNotification(int32_t id, uint32_t durationMs) {
836 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
837 : "Channel::PlayNotification(id=%d, durationMs=%d)", id,
838 : durationMs);
839 :
840 : // Not implement yet
841 0 : }
842 :
843 0 : void Channel::RecordNotification(int32_t id, uint32_t durationMs) {
844 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
845 : "Channel::RecordNotification(id=%d, durationMs=%d)", id,
846 : durationMs);
847 :
848 : // Not implement yet
849 0 : }
850 :
851 0 : void Channel::PlayFileEnded(int32_t id) {
852 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
853 : "Channel::PlayFileEnded(id=%d)", id);
854 :
855 0 : if (id == _inputFilePlayerId) {
856 0 : channel_state_.SetInputFilePlaying(false);
857 : WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
858 : "Channel::PlayFileEnded() => input file player module is"
859 : " shutdown");
860 0 : } else if (id == _outputFilePlayerId) {
861 0 : channel_state_.SetOutputFilePlaying(false);
862 : WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
863 : "Channel::PlayFileEnded() => output file player module is"
864 : " shutdown");
865 : }
866 0 : }
867 :
868 0 : void Channel::RecordFileEnded(int32_t id) {
869 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
870 : "Channel::RecordFileEnded(id=%d)", id);
871 :
872 0 : assert(id == _outputFileRecorderId);
873 :
874 0 : rtc::CritScope cs(&_fileCritSect);
875 :
876 0 : _outputFileRecording = false;
877 : WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
878 : "Channel::RecordFileEnded() => output file recorder module is"
879 : " shutdown");
880 0 : }
881 :
882 0 : Channel::Channel(int32_t channelId,
883 : uint32_t instanceId,
884 0 : const VoEBase::ChannelConfig& config)
885 : : _instanceId(instanceId),
886 : _channelId(channelId),
887 0 : event_log_proxy_(new RtcEventLogProxy()),
888 0 : rtcp_rtt_stats_proxy_(new RtcpRttStatsProxy()),
889 : rtp_header_parser_(RtpHeaderParser::Create()),
890 0 : rtp_payload_registry_(new RTPPayloadRegistry()),
891 : rtp_receive_statistics_(
892 : ReceiveStatistics::Create(Clock::GetRealTimeClock())),
893 : rtp_receiver_(
894 : RtpReceiver::CreateAudioReceiver(Clock::GetRealTimeClock(),
895 : this,
896 : this,
897 : rtp_payload_registry_.get())),
898 0 : telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()),
899 : _outputAudioLevel(),
900 : _externalTransport(false),
901 : // Avoid conflict with other channels by adding 1024 - 1026,
902 : // won't use as much as 1024 channels.
903 0 : _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
904 0 : _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
905 0 : _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
906 : _outputFileRecording(false),
907 : _outputExternalMedia(false),
908 : _inputExternalMediaCallbackPtr(NULL),
909 : _outputExternalMediaCallbackPtr(NULL),
910 : _timeStamp(0), // This is just an offset, RTP module will add it's own
911 : // random offset
912 : ntp_estimator_(Clock::GetRealTimeClock()),
913 : playout_timestamp_rtp_(0),
914 : playout_timestamp_rtcp_(0),
915 : playout_delay_ms_(0),
916 : _numberOfDiscardedPackets(0),
917 : send_sequence_number_(0),
918 0 : rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()),
919 : capture_start_rtp_time_stamp_(-1),
920 : capture_start_ntp_time_ms_(-1),
921 : _engineStatisticsPtr(NULL),
922 : _outputMixerPtr(NULL),
923 : _transmitMixerPtr(NULL),
924 : _moduleProcessThreadPtr(NULL),
925 : _audioDeviceModulePtr(NULL),
926 : _voiceEngineObserverPtr(NULL),
927 : _callbackCritSectPtr(NULL),
928 : _transportPtr(NULL),
929 : _sendFrameType(0),
930 : _externalMixing(false),
931 : _mixFileWithMicrophone(false),
932 : input_mute_(false),
933 : previous_frame_muted_(false),
934 : _panLeft(1.0f),
935 : _panRight(1.0f),
936 : _outputGain(1.0f),
937 : _lastLocalTimeStamp(0),
938 : _lastPayloadType(0),
939 : _includeAudioLevelIndication(false),
940 : transport_overhead_per_packet_(0),
941 : rtp_overhead_per_packet_(0),
942 : _outputSpeechType(AudioFrame::kNormalSpeech),
943 : _current_sync_offset(0),
944 : restored_packet_in_use_(false),
945 0 : rtcp_observer_(new VoERtcpObserver(this)),
946 : associate_send_channel_(ChannelOwner(nullptr)),
947 0 : pacing_enabled_(config.enable_voice_pacing),
948 0 : feedback_observer_proxy_(new TransportFeedbackProxy()),
949 0 : seq_num_allocator_proxy_(new TransportSequenceNumberProxy()),
950 0 : rtp_packet_sender_proxy_(new RtpPacketSenderProxy()),
951 0 : retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(),
952 0 : kMaxRetransmissionWindowMs)),
953 0 : decoder_factory_(config.acm_config.decoder_factory) {
954 : WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, _channelId),
955 : "Channel::Channel() - ctor");
956 0 : AudioCodingModule::Config acm_config(config.acm_config);
957 0 : acm_config.id = VoEModuleId(instanceId, channelId);
958 0 : acm_config.neteq_config.enable_muted_state = true;
959 0 : audio_coding_.reset(AudioCodingModule::Create(acm_config));
960 :
961 0 : _outputAudioLevel.Clear();
962 :
963 0 : RtpRtcp::Configuration configuration;
964 0 : configuration.audio = true;
965 0 : configuration.outgoing_transport = this;
966 0 : configuration.overhead_observer = this;
967 0 : configuration.receive_statistics = rtp_receive_statistics_.get();
968 0 : configuration.bandwidth_callback = rtcp_observer_.get();
969 0 : if (pacing_enabled_) {
970 0 : configuration.paced_sender = rtp_packet_sender_proxy_.get();
971 0 : configuration.transport_sequence_number_allocator =
972 0 : seq_num_allocator_proxy_.get();
973 0 : configuration.transport_feedback_callback = feedback_observer_proxy_.get();
974 : }
975 0 : configuration.event_log = &(*event_log_proxy_);
976 0 : configuration.rtt_stats = &(*rtcp_rtt_stats_proxy_);
977 0 : configuration.retransmission_rate_limiter =
978 0 : retransmission_rate_limiter_.get();
979 :
980 0 : configuration.rtcp_packet_type_counter_observer = statistics_proxy_.get();
981 :
982 0 : _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
983 0 : _rtpRtcpModule->SetSendingMediaStatus(false);
984 :
985 0 : statistics_proxy_.reset(new StatisticsProxy(_rtpRtcpModule->SSRC()));
986 0 : rtp_receive_statistics_->RegisterRtcpStatisticsCallback(
987 0 : statistics_proxy_.get());
988 0 : }
989 :
990 0 : Channel::~Channel() {
991 0 : rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL);
992 : WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, _channelId),
993 : "Channel::~Channel() - dtor");
994 :
995 0 : if (_outputExternalMedia) {
996 0 : DeRegisterExternalMediaProcessing(kPlaybackPerChannel);
997 : }
998 0 : if (channel_state_.Get().input_external_media) {
999 0 : DeRegisterExternalMediaProcessing(kRecordingPerChannel);
1000 : }
1001 0 : StopSend();
1002 0 : StopPlayout();
1003 :
1004 : {
1005 0 : rtc::CritScope cs(&_fileCritSect);
1006 0 : if (input_file_player_) {
1007 0 : input_file_player_->RegisterModuleFileCallback(NULL);
1008 0 : input_file_player_->StopPlayingFile();
1009 : }
1010 0 : if (output_file_player_) {
1011 0 : output_file_player_->RegisterModuleFileCallback(NULL);
1012 0 : output_file_player_->StopPlayingFile();
1013 : }
1014 0 : if (output_file_recorder_) {
1015 0 : output_file_recorder_->RegisterModuleFileCallback(NULL);
1016 0 : output_file_recorder_->StopRecording();
1017 : }
1018 : }
1019 :
1020 : // The order to safely shutdown modules in a channel is:
1021 : // 1. De-register callbacks in modules
1022 : // 2. De-register modules in process thread
1023 : // 3. Destroy modules
1024 0 : if (audio_coding_->RegisterTransportCallback(NULL) == -1) {
1025 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1026 : "~Channel() failed to de-register transport callback"
1027 : " (Audio coding module)");
1028 : }
1029 0 : if (audio_coding_->RegisterVADCallback(NULL) == -1) {
1030 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1031 : "~Channel() failed to de-register VAD callback"
1032 : " (Audio coding module)");
1033 : }
1034 : // De-register modules in process thread
1035 0 : _moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get());
1036 :
1037 : // End of modules shutdown
1038 0 : }
1039 :
1040 0 : int32_t Channel::Init() {
1041 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1042 : "Channel::Init()");
1043 :
1044 0 : channel_state_.Reset();
1045 :
1046 : // --- Initial sanity
1047 :
1048 0 : if ((_engineStatisticsPtr == NULL) || (_moduleProcessThreadPtr == NULL)) {
1049 : WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
1050 : "Channel::Init() must call SetEngineInformation() first");
1051 0 : return -1;
1052 : }
1053 :
1054 : // --- Add modules to process thread (for periodic schedulation)
1055 :
1056 0 : _moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get());
1057 :
1058 : // --- ACM initialization
1059 :
1060 0 : if (audio_coding_->InitializeReceiver() == -1) {
1061 0 : _engineStatisticsPtr->SetLastError(
1062 : VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1063 0 : "Channel::Init() unable to initialize the ACM - 1");
1064 0 : return -1;
1065 : }
1066 :
1067 : // --- RTP/RTCP module initialization
1068 :
1069 : // Ensure that RTCP is enabled by default for the created channel.
1070 : // Note that, the module will keep generating RTCP until it is explicitly
1071 : // disabled by the user.
1072 : // After StopListen (when no sockets exists), RTCP packets will no longer
1073 : // be transmitted since the Transport object will then be invalid.
1074 0 : telephone_event_handler_->SetTelephoneEventForwardToDecoder(true);
1075 : // RTCP is enabled by default.
1076 0 : _rtpRtcpModule->SetRTCPStatus(RtcpMode::kCompound);
1077 : // --- Register all permanent callbacks
1078 0 : const bool fail = (audio_coding_->RegisterTransportCallback(this) == -1) ||
1079 0 : (audio_coding_->RegisterVADCallback(this) == -1);
1080 :
1081 0 : if (fail) {
1082 0 : _engineStatisticsPtr->SetLastError(
1083 : VE_CANNOT_INIT_CHANNEL, kTraceError,
1084 0 : "Channel::Init() callbacks not registered");
1085 0 : return -1;
1086 : }
1087 :
1088 : // --- Register all supported codecs to the receiving side of the
1089 : // RTP/RTCP module
1090 :
1091 : CodecInst codec;
1092 0 : const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
1093 :
1094 0 : for (int idx = 0; idx < nSupportedCodecs; idx++) {
1095 : // Open up the RTP/RTCP receiver for all supported codecs
1096 0 : if ((audio_coding_->Codec(idx, &codec) == -1) ||
1097 0 : (rtp_receiver_->RegisterReceivePayload(codec) == -1)) {
1098 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1099 : "Channel::Init() unable to register %s "
1100 : "(%d/%d/%" PRIuS "/%d) to RTP/RTCP receiver",
1101 : codec.plname, codec.pltype, codec.plfreq, codec.channels,
1102 : codec.rate);
1103 : } else {
1104 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1105 : "Channel::Init() %s (%d/%d/%" PRIuS
1106 : "/%d) has been "
1107 : "added to the RTP/RTCP receiver",
1108 : codec.plname, codec.pltype, codec.plfreq, codec.channels,
1109 : codec.rate);
1110 : }
1111 :
1112 : // Ensure that PCMU is used as default codec on the sending side
1113 0 : if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1)) {
1114 0 : SetSendCodec(codec);
1115 : }
1116 :
1117 : // Register default PT for outband 'telephone-event'
1118 0 : if (!STR_CASE_CMP(codec.plname, "telephone-event")) {
1119 0 : if (_rtpRtcpModule->RegisterSendPayload(codec) == -1 ||
1120 0 : !audio_coding_->RegisterReceiveCodec(codec.pltype,
1121 0 : CodecInstToSdp(codec))) {
1122 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1123 : "Channel::Init() failed to register outband "
1124 : "'telephone-event' (%d/%d) correctly",
1125 : codec.pltype, codec.plfreq);
1126 : }
1127 : }
1128 :
1129 0 : if (!STR_CASE_CMP(codec.plname, "CN")) {
1130 0 : if (!codec_manager_.RegisterEncoder(codec) ||
1131 0 : !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get()) ||
1132 0 : !audio_coding_->RegisterReceiveCodec(codec.pltype,
1133 0 : CodecInstToSdp(codec)) ||
1134 0 : _rtpRtcpModule->RegisterSendPayload(codec) == -1) {
1135 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1136 : "Channel::Init() failed to register CN (%d/%d) "
1137 : "correctly - 1",
1138 : codec.pltype, codec.plfreq);
1139 : }
1140 : }
1141 : }
1142 :
1143 0 : return 0;
1144 : }
1145 :
1146 0 : int32_t Channel::SetEngineInformation(Statistics& engineStatistics,
1147 : OutputMixer& outputMixer,
1148 : voe::TransmitMixer& transmitMixer,
1149 : ProcessThread& moduleProcessThread,
1150 : AudioDeviceModule& audioDeviceModule,
1151 : VoiceEngineObserver* voiceEngineObserver,
1152 : rtc::CriticalSection* callbackCritSect) {
1153 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1154 : "Channel::SetEngineInformation()");
1155 0 : _engineStatisticsPtr = &engineStatistics;
1156 0 : _outputMixerPtr = &outputMixer;
1157 0 : _transmitMixerPtr = &transmitMixer;
1158 0 : _moduleProcessThreadPtr = &moduleProcessThread;
1159 0 : _audioDeviceModulePtr = &audioDeviceModule;
1160 0 : _voiceEngineObserverPtr = voiceEngineObserver;
1161 0 : _callbackCritSectPtr = callbackCritSect;
1162 0 : return 0;
1163 : }
1164 :
1165 0 : int32_t Channel::UpdateLocalTimeStamp() {
1166 0 : _timeStamp += static_cast<uint32_t>(_audioFrame.samples_per_channel_);
1167 0 : return 0;
1168 : }
1169 :
1170 0 : void Channel::SetSink(std::unique_ptr<AudioSinkInterface> sink) {
1171 0 : rtc::CritScope cs(&_callbackCritSect);
1172 0 : audio_sink_ = std::move(sink);
1173 0 : }
1174 :
1175 : const rtc::scoped_refptr<AudioDecoderFactory>&
1176 0 : Channel::GetAudioDecoderFactory() const {
1177 0 : return decoder_factory_;
1178 : }
1179 :
1180 0 : int32_t Channel::StartPlayout() {
1181 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1182 : "Channel::StartPlayout()");
1183 0 : if (channel_state_.Get().playing) {
1184 0 : return 0;
1185 : }
1186 :
1187 0 : if (!_externalMixing) {
1188 : // Add participant as candidates for mixing.
1189 0 : if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0) {
1190 0 : _engineStatisticsPtr->SetLastError(
1191 : VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1192 0 : "StartPlayout() failed to add participant to mixer");
1193 0 : return -1;
1194 : }
1195 : }
1196 :
1197 0 : channel_state_.SetPlaying(true);
1198 0 : if (RegisterFilePlayingToMixer() != 0)
1199 0 : return -1;
1200 :
1201 0 : return 0;
1202 : }
1203 :
1204 0 : int32_t Channel::StopPlayout() {
1205 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1206 : "Channel::StopPlayout()");
1207 0 : if (!channel_state_.Get().playing) {
1208 0 : return 0;
1209 : }
1210 :
1211 0 : if (!_externalMixing) {
1212 : // Remove participant as candidates for mixing
1213 0 : if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0) {
1214 0 : _engineStatisticsPtr->SetLastError(
1215 : VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1216 0 : "StopPlayout() failed to remove participant from mixer");
1217 0 : return -1;
1218 : }
1219 : }
1220 :
1221 0 : channel_state_.SetPlaying(false);
1222 0 : _outputAudioLevel.Clear();
1223 :
1224 0 : return 0;
1225 : }
1226 :
1227 0 : int32_t Channel::StartSend() {
1228 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1229 : "Channel::StartSend()");
1230 : // Resume the previous sequence number which was reset by StopSend().
1231 : // This needs to be done before |sending| is set to true.
1232 0 : if (send_sequence_number_)
1233 0 : SetInitSequenceNumber(send_sequence_number_);
1234 :
1235 0 : if (channel_state_.Get().sending) {
1236 0 : return 0;
1237 : }
1238 0 : channel_state_.SetSending(true);
1239 :
1240 0 : _rtpRtcpModule->SetSendingMediaStatus(true);
1241 0 : if (_rtpRtcpModule->SetSendingStatus(true) != 0) {
1242 0 : _engineStatisticsPtr->SetLastError(
1243 : VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1244 0 : "StartSend() RTP/RTCP failed to start sending");
1245 0 : _rtpRtcpModule->SetSendingMediaStatus(false);
1246 0 : rtc::CritScope cs(&_callbackCritSect);
1247 0 : channel_state_.SetSending(false);
1248 0 : return -1;
1249 : }
1250 :
1251 0 : return 0;
1252 : }
1253 :
1254 0 : int32_t Channel::StopSend() {
1255 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1256 : "Channel::StopSend()");
1257 0 : if (!channel_state_.Get().sending) {
1258 0 : return 0;
1259 : }
1260 0 : channel_state_.SetSending(false);
1261 :
1262 : // Store the sequence number to be able to pick up the same sequence for
1263 : // the next StartSend(). This is needed for restarting device, otherwise
1264 : // it might cause libSRTP to complain about packets being replayed.
1265 : // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring
1266 : // CL is landed. See issue
1267 : // https://code.google.com/p/webrtc/issues/detail?id=2111 .
1268 0 : send_sequence_number_ = _rtpRtcpModule->SequenceNumber();
1269 :
1270 : // Reset sending SSRC and sequence number and triggers direct transmission
1271 : // of RTCP BYE
1272 0 : if (_rtpRtcpModule->SetSendingStatus(false) == -1) {
1273 0 : _engineStatisticsPtr->SetLastError(
1274 : VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1275 0 : "StartSend() RTP/RTCP failed to stop sending");
1276 : }
1277 0 : _rtpRtcpModule->SetSendingMediaStatus(false);
1278 :
1279 0 : return 0;
1280 : }
1281 :
1282 0 : void Channel::ResetDiscardedPacketCount() {
1283 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1284 : "Channel::ResetDiscardedPacketCount()");
1285 0 : _numberOfDiscardedPackets = 0;
1286 0 : }
1287 :
1288 0 : int32_t Channel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer) {
1289 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1290 : "Channel::RegisterVoiceEngineObserver()");
1291 0 : rtc::CritScope cs(&_callbackCritSect);
1292 :
1293 0 : if (_voiceEngineObserverPtr) {
1294 0 : _engineStatisticsPtr->SetLastError(
1295 : VE_INVALID_OPERATION, kTraceError,
1296 0 : "RegisterVoiceEngineObserver() observer already enabled");
1297 0 : return -1;
1298 : }
1299 0 : _voiceEngineObserverPtr = &observer;
1300 0 : return 0;
1301 : }
1302 :
1303 0 : int32_t Channel::DeRegisterVoiceEngineObserver() {
1304 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1305 : "Channel::DeRegisterVoiceEngineObserver()");
1306 0 : rtc::CritScope cs(&_callbackCritSect);
1307 :
1308 0 : if (!_voiceEngineObserverPtr) {
1309 0 : _engineStatisticsPtr->SetLastError(
1310 : VE_INVALID_OPERATION, kTraceWarning,
1311 0 : "DeRegisterVoiceEngineObserver() observer already disabled");
1312 0 : return 0;
1313 : }
1314 0 : _voiceEngineObserverPtr = NULL;
1315 0 : return 0;
1316 : }
1317 :
1318 0 : int32_t Channel::GetSendCodec(CodecInst& codec) {
1319 0 : auto send_codec = codec_manager_.GetCodecInst();
1320 0 : if (send_codec) {
1321 0 : codec = *send_codec;
1322 0 : return 0;
1323 : }
1324 0 : return -1;
1325 : }
1326 :
1327 0 : int32_t Channel::GetRecCodec(CodecInst& codec) {
1328 0 : return (audio_coding_->ReceiveCodec(&codec));
1329 : }
1330 :
1331 0 : int32_t Channel::SetSendCodec(const CodecInst& codec) {
1332 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1333 : "Channel::SetSendCodec()");
1334 :
1335 0 : if (!codec_manager_.RegisterEncoder(codec) ||
1336 0 : !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
1337 : WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
1338 : "SetSendCodec() failed to register codec to ACM");
1339 0 : return -1;
1340 : }
1341 :
1342 0 : if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1343 0 : _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1344 0 : if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1345 : WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
1346 : "SetSendCodec() failed to register codec to"
1347 : " RTP/RTCP module");
1348 0 : return -1;
1349 : }
1350 : }
1351 :
1352 0 : return 0;
1353 : }
1354 :
1355 0 : void Channel::SetBitRate(int bitrate_bps, int64_t probing_interval_ms) {
1356 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1357 : "Channel::SetBitRate(bitrate_bps=%d)", bitrate_bps);
1358 0 : audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1359 0 : if (*encoder) {
1360 0 : (*encoder)->OnReceivedUplinkBandwidth(
1361 0 : bitrate_bps, rtc::Optional<int64_t>(probing_interval_ms));
1362 : }
1363 0 : });
1364 0 : retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
1365 0 : }
1366 :
1367 0 : void Channel::OnIncomingFractionLoss(int fraction_lost) {
1368 0 : audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1369 0 : if (*encoder)
1370 0 : (*encoder)->OnReceivedUplinkPacketLossFraction(fraction_lost / 255.0f);
1371 0 : });
1372 0 : }
1373 :
1374 0 : int32_t Channel::SetVADStatus(bool enableVAD,
1375 : ACMVADMode mode,
1376 : bool disableDTX) {
1377 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1378 : "Channel::SetVADStatus(mode=%d)", mode);
1379 0 : RTC_DCHECK(!(disableDTX && enableVAD)); // disableDTX mode is deprecated.
1380 0 : if (!codec_manager_.SetVAD(enableVAD, mode) ||
1381 0 : !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
1382 0 : _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR,
1383 : kTraceError,
1384 0 : "SetVADStatus() failed to set VAD");
1385 0 : return -1;
1386 : }
1387 0 : return 0;
1388 : }
1389 :
1390 0 : int32_t Channel::GetVADStatus(bool& enabledVAD,
1391 : ACMVADMode& mode,
1392 : bool& disabledDTX) {
1393 0 : const auto* params = codec_manager_.GetStackParams();
1394 0 : enabledVAD = params->use_cng;
1395 0 : mode = params->vad_mode;
1396 0 : disabledDTX = !params->use_cng;
1397 0 : return 0;
1398 : }
1399 :
1400 0 : int32_t Channel::SetRecPayloadType(const CodecInst& codec) {
1401 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1402 : "Channel::SetRecPayloadType()");
1403 :
1404 0 : if (channel_state_.Get().playing) {
1405 0 : _engineStatisticsPtr->SetLastError(
1406 : VE_ALREADY_PLAYING, kTraceError,
1407 0 : "SetRecPayloadType() unable to set PT while playing");
1408 0 : return -1;
1409 : }
1410 :
1411 0 : if (codec.pltype == -1) {
1412 : // De-register the selected codec (RTP/RTCP module and ACM)
1413 :
1414 0 : int8_t pltype(-1);
1415 0 : CodecInst rxCodec = codec;
1416 :
1417 : // Get payload type for the given codec
1418 0 : rtp_payload_registry_->ReceivePayloadType(rxCodec, &pltype);
1419 0 : rxCodec.pltype = pltype;
1420 :
1421 0 : if (rtp_receiver_->DeRegisterReceivePayload(pltype) != 0) {
1422 0 : _engineStatisticsPtr->SetLastError(
1423 : VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1424 : "SetRecPayloadType() RTP/RTCP-module deregistration "
1425 0 : "failed");
1426 0 : return -1;
1427 : }
1428 0 : if (audio_coding_->UnregisterReceiveCodec(rxCodec.pltype) != 0) {
1429 0 : _engineStatisticsPtr->SetLastError(
1430 : VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1431 0 : "SetRecPayloadType() ACM deregistration failed - 1");
1432 0 : return -1;
1433 : }
1434 0 : return 0;
1435 : }
1436 :
1437 0 : if (rtp_receiver_->RegisterReceivePayload(codec) != 0) {
1438 : // First attempt to register failed => de-register and try again
1439 : // TODO(kwiberg): Retrying is probably not necessary, since
1440 : // AcmReceiver::AddCodec also retries.
1441 0 : rtp_receiver_->DeRegisterReceivePayload(codec.pltype);
1442 0 : if (rtp_receiver_->RegisterReceivePayload(codec) != 0) {
1443 0 : _engineStatisticsPtr->SetLastError(
1444 : VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1445 0 : "SetRecPayloadType() RTP/RTCP-module registration failed");
1446 0 : return -1;
1447 : }
1448 : }
1449 0 : if (!audio_coding_->RegisterReceiveCodec(codec.pltype,
1450 0 : CodecInstToSdp(codec))) {
1451 0 : audio_coding_->UnregisterReceiveCodec(codec.pltype);
1452 0 : if (!audio_coding_->RegisterReceiveCodec(codec.pltype,
1453 0 : CodecInstToSdp(codec))) {
1454 0 : _engineStatisticsPtr->SetLastError(
1455 : VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1456 0 : "SetRecPayloadType() ACM registration failed - 1");
1457 0 : return -1;
1458 : }
1459 : }
1460 0 : return 0;
1461 : }
1462 :
1463 0 : int32_t Channel::GetRecPayloadType(CodecInst& codec) {
1464 0 : int8_t payloadType(-1);
1465 0 : if (rtp_payload_registry_->ReceivePayloadType(codec, &payloadType) != 0) {
1466 0 : _engineStatisticsPtr->SetLastError(
1467 : VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1468 0 : "GetRecPayloadType() failed to retrieve RX payload type");
1469 0 : return -1;
1470 : }
1471 0 : codec.pltype = payloadType;
1472 0 : return 0;
1473 : }
1474 :
1475 0 : int32_t Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency) {
1476 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1477 : "Channel::SetSendCNPayloadType()");
1478 :
1479 : CodecInst codec;
1480 0 : int32_t samplingFreqHz(-1);
1481 0 : const size_t kMono = 1;
1482 0 : if (frequency == kFreq32000Hz)
1483 0 : samplingFreqHz = 32000;
1484 0 : else if (frequency == kFreq16000Hz)
1485 0 : samplingFreqHz = 16000;
1486 :
1487 0 : if (audio_coding_->Codec("CN", &codec, samplingFreqHz, kMono) == -1) {
1488 0 : _engineStatisticsPtr->SetLastError(
1489 : VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1490 : "SetSendCNPayloadType() failed to retrieve default CN codec "
1491 0 : "settings");
1492 0 : return -1;
1493 : }
1494 :
1495 : // Modify the payload type (must be set to dynamic range)
1496 0 : codec.pltype = type;
1497 :
1498 0 : if (!codec_manager_.RegisterEncoder(codec) ||
1499 0 : !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
1500 0 : _engineStatisticsPtr->SetLastError(
1501 : VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1502 0 : "SetSendCNPayloadType() failed to register CN to ACM");
1503 0 : return -1;
1504 : }
1505 :
1506 0 : if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1507 0 : _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1508 0 : if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1509 0 : _engineStatisticsPtr->SetLastError(
1510 : VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1511 : "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
1512 0 : "module");
1513 0 : return -1;
1514 : }
1515 : }
1516 0 : return 0;
1517 : }
1518 :
1519 0 : int Channel::SetOpusMaxPlaybackRate(int frequency_hz) {
1520 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1521 : "Channel::SetOpusMaxPlaybackRate()");
1522 :
1523 0 : if (audio_coding_->SetOpusMaxPlaybackRate(frequency_hz) != 0) {
1524 0 : _engineStatisticsPtr->SetLastError(
1525 : VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1526 0 : "SetOpusMaxPlaybackRate() failed to set maximum playback rate");
1527 0 : return -1;
1528 : }
1529 0 : return 0;
1530 : }
1531 :
1532 0 : int Channel::SetOpusDtx(bool enable_dtx) {
1533 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1534 : "Channel::SetOpusDtx(%d)", enable_dtx);
1535 0 : int ret = enable_dtx ? audio_coding_->EnableOpusDtx()
1536 0 : : audio_coding_->DisableOpusDtx();
1537 0 : if (ret != 0) {
1538 0 : _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR,
1539 0 : kTraceError, "SetOpusDtx() failed");
1540 0 : return -1;
1541 : }
1542 0 : return 0;
1543 : }
1544 :
1545 0 : int Channel::GetOpusDtx(bool* enabled) {
1546 0 : int success = -1;
1547 0 : audio_coding_->QueryEncoder([&](AudioEncoder const* encoder) {
1548 0 : if (encoder) {
1549 0 : *enabled = encoder->GetDtx();
1550 0 : success = 0;
1551 : }
1552 0 : });
1553 0 : return success;
1554 : }
1555 :
1556 0 : bool Channel::EnableAudioNetworkAdaptor(const std::string& config_string) {
1557 0 : bool success = false;
1558 0 : audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1559 0 : if (*encoder) {
1560 0 : success = (*encoder)->EnableAudioNetworkAdaptor(
1561 0 : config_string, event_log_proxy_.get(), Clock::GetRealTimeClock());
1562 : }
1563 0 : });
1564 0 : return success;
1565 : }
1566 :
1567 0 : void Channel::DisableAudioNetworkAdaptor() {
1568 0 : audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1569 0 : if (*encoder)
1570 0 : (*encoder)->DisableAudioNetworkAdaptor();
1571 0 : });
1572 0 : }
1573 :
1574 0 : void Channel::SetReceiverFrameLengthRange(int min_frame_length_ms,
1575 : int max_frame_length_ms) {
1576 0 : audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1577 0 : if (*encoder) {
1578 0 : (*encoder)->SetReceiverFrameLengthRange(min_frame_length_ms,
1579 0 : max_frame_length_ms);
1580 : }
1581 0 : });
1582 0 : }
1583 :
1584 0 : int32_t Channel::RegisterExternalTransport(Transport* transport) {
1585 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1586 : "Channel::RegisterExternalTransport()");
1587 :
1588 0 : rtc::CritScope cs(&_callbackCritSect);
1589 0 : if (_externalTransport) {
1590 0 : _engineStatisticsPtr->SetLastError(
1591 : VE_INVALID_OPERATION, kTraceError,
1592 0 : "RegisterExternalTransport() external transport already enabled");
1593 0 : return -1;
1594 : }
1595 0 : _externalTransport = true;
1596 0 : _transportPtr = transport;
1597 0 : return 0;
1598 : }
1599 :
1600 0 : int32_t Channel::DeRegisterExternalTransport() {
1601 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1602 : "Channel::DeRegisterExternalTransport()");
1603 :
1604 0 : rtc::CritScope cs(&_callbackCritSect);
1605 0 : if (_transportPtr) {
1606 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1607 : "DeRegisterExternalTransport() all transport is disabled");
1608 : } else {
1609 0 : _engineStatisticsPtr->SetLastError(
1610 : VE_INVALID_OPERATION, kTraceWarning,
1611 : "DeRegisterExternalTransport() external transport already "
1612 0 : "disabled");
1613 : }
1614 0 : _externalTransport = false;
1615 0 : _transportPtr = NULL;
1616 0 : return 0;
1617 : }
1618 :
1619 0 : int32_t Channel::ReceivedRTPPacket(const uint8_t* received_packet,
1620 : size_t length,
1621 : const PacketTime& packet_time) {
1622 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
1623 : "Channel::ReceivedRTPPacket()");
1624 :
1625 : // Store playout timestamp for the received RTP packet
1626 0 : UpdatePlayoutTimestamp(false);
1627 :
1628 0 : RTPHeader header;
1629 0 : if (!rtp_header_parser_->Parse(received_packet, length, &header)) {
1630 : WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1631 : "Incoming packet: invalid RTP header");
1632 0 : return -1;
1633 : }
1634 0 : header.payload_type_frequency =
1635 0 : rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
1636 0 : if (header.payload_type_frequency < 0)
1637 0 : return -1;
1638 0 : bool in_order = IsPacketInOrder(header);
1639 0 : rtp_receive_statistics_->IncomingPacket(
1640 0 : header, length, IsPacketRetransmitted(header, in_order));
1641 0 : rtp_payload_registry_->SetIncomingPayloadType(header);
1642 :
1643 0 : return ReceivePacket(received_packet, length, header, in_order) ? 0 : -1;
1644 : }
1645 :
1646 0 : bool Channel::ReceivePacket(const uint8_t* packet,
1647 : size_t packet_length,
1648 : const RTPHeader& header,
1649 : bool in_order) {
1650 0 : if (rtp_payload_registry_->IsRtx(header)) {
1651 0 : return HandleRtxPacket(packet, packet_length, header);
1652 : }
1653 0 : const uint8_t* payload = packet + header.headerLength;
1654 0 : assert(packet_length >= header.headerLength);
1655 0 : size_t payload_length = packet_length - header.headerLength;
1656 : PayloadUnion payload_specific;
1657 0 : if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
1658 : &payload_specific)) {
1659 0 : return false;
1660 : }
1661 0 : return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
1662 0 : payload_specific, in_order);
1663 : }
1664 :
1665 0 : bool Channel::HandleRtxPacket(const uint8_t* packet,
1666 : size_t packet_length,
1667 : const RTPHeader& header) {
1668 0 : if (!rtp_payload_registry_->IsRtx(header))
1669 0 : return false;
1670 :
1671 : // Remove the RTX header and parse the original RTP header.
1672 0 : if (packet_length < header.headerLength)
1673 0 : return false;
1674 0 : if (packet_length > kVoiceEngineMaxIpPacketSizeBytes)
1675 0 : return false;
1676 0 : if (restored_packet_in_use_) {
1677 : WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1678 : "Multiple RTX headers detected, dropping packet");
1679 0 : return false;
1680 : }
1681 0 : if (!rtp_payload_registry_->RestoreOriginalPacket(
1682 0 : restored_packet_, packet, &packet_length, rtp_receiver_->SSRC(),
1683 : header)) {
1684 : WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1685 : "Incoming RTX packet: invalid RTP header");
1686 0 : return false;
1687 : }
1688 0 : restored_packet_in_use_ = true;
1689 0 : bool ret = OnRecoveredPacket(restored_packet_, packet_length);
1690 0 : restored_packet_in_use_ = false;
1691 0 : return ret;
1692 : }
1693 :
1694 0 : bool Channel::IsPacketInOrder(const RTPHeader& header) const {
1695 : StreamStatistician* statistician =
1696 0 : rtp_receive_statistics_->GetStatistician(header.ssrc);
1697 0 : if (!statistician)
1698 0 : return false;
1699 0 : return statistician->IsPacketInOrder(header.sequenceNumber);
1700 : }
1701 :
1702 0 : bool Channel::IsPacketRetransmitted(const RTPHeader& header,
1703 : bool in_order) const {
1704 : // Retransmissions are handled separately if RTX is enabled.
1705 0 : if (rtp_payload_registry_->RtxEnabled())
1706 0 : return false;
1707 : StreamStatistician* statistician =
1708 0 : rtp_receive_statistics_->GetStatistician(header.ssrc);
1709 0 : if (!statistician)
1710 0 : return false;
1711 : // Check if this is a retransmission.
1712 0 : int64_t min_rtt = 0;
1713 0 : _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
1714 0 : return !in_order && statistician->IsRetransmitOfOldPacket(header, min_rtt);
1715 : }
1716 :
1717 0 : int32_t Channel::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
1718 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
1719 : "Channel::ReceivedRTCPPacket()");
1720 : // Store playout timestamp for the received RTCP packet
1721 0 : UpdatePlayoutTimestamp(true);
1722 :
1723 : // Deliver RTCP packet to RTP/RTCP module for parsing
1724 0 : if (_rtpRtcpModule->IncomingRtcpPacket(data, length) == -1) {
1725 0 : _engineStatisticsPtr->SetLastError(
1726 : VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
1727 0 : "Channel::IncomingRTPPacket() RTCP packet is invalid");
1728 : }
1729 :
1730 0 : int64_t rtt = GetRTT(true);
1731 0 : if (rtt == 0) {
1732 : // Waiting for valid RTT.
1733 0 : return 0;
1734 : }
1735 :
1736 0 : int64_t nack_window_ms = rtt;
1737 0 : if (nack_window_ms < kMinRetransmissionWindowMs) {
1738 0 : nack_window_ms = kMinRetransmissionWindowMs;
1739 0 : } else if (nack_window_ms > kMaxRetransmissionWindowMs) {
1740 0 : nack_window_ms = kMaxRetransmissionWindowMs;
1741 : }
1742 0 : retransmission_rate_limiter_->SetWindowSize(nack_window_ms);
1743 :
1744 : // Invoke audio encoders OnReceivedRtt().
1745 0 : audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1746 0 : if (*encoder)
1747 0 : (*encoder)->OnReceivedRtt(rtt);
1748 0 : });
1749 :
1750 0 : uint32_t ntp_secs = 0;
1751 0 : uint32_t ntp_frac = 0;
1752 0 : uint32_t rtp_timestamp = 0;
1753 0 : if (0 !=
1754 0 : _rtpRtcpModule->RemoteNTP(&ntp_secs, &ntp_frac, NULL, NULL,
1755 0 : &rtp_timestamp)) {
1756 : // Waiting for RTCP.
1757 0 : return 0;
1758 : }
1759 :
1760 : {
1761 0 : rtc::CritScope lock(&ts_stats_lock_);
1762 0 : ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp);
1763 : }
1764 0 : return 0;
1765 : }
1766 :
1767 0 : int Channel::StartPlayingFileLocally(const char* fileName,
1768 : bool loop,
1769 : FileFormats format,
1770 : int startPosition,
1771 : float volumeScaling,
1772 : int stopPosition,
1773 : const CodecInst* codecInst) {
1774 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1775 : "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
1776 : " format=%d, volumeScaling=%5.3f, startPosition=%d, "
1777 : "stopPosition=%d)",
1778 : fileName, loop, format, volumeScaling, startPosition,
1779 : stopPosition);
1780 :
1781 0 : if (channel_state_.Get().output_file_playing) {
1782 0 : _engineStatisticsPtr->SetLastError(
1783 : VE_ALREADY_PLAYING, kTraceError,
1784 0 : "StartPlayingFileLocally() is already playing");
1785 0 : return -1;
1786 : }
1787 :
1788 : {
1789 0 : rtc::CritScope cs(&_fileCritSect);
1790 :
1791 0 : if (output_file_player_) {
1792 0 : output_file_player_->RegisterModuleFileCallback(NULL);
1793 0 : output_file_player_.reset();
1794 : }
1795 :
1796 0 : output_file_player_ = FilePlayer::CreateFilePlayer(
1797 0 : _outputFilePlayerId, (const FileFormats)format);
1798 :
1799 0 : if (!output_file_player_) {
1800 0 : _engineStatisticsPtr->SetLastError(
1801 : VE_INVALID_ARGUMENT, kTraceError,
1802 0 : "StartPlayingFileLocally() filePlayer format is not correct");
1803 0 : return -1;
1804 : }
1805 :
1806 0 : const uint32_t notificationTime(0);
1807 :
1808 0 : if (output_file_player_->StartPlayingFile(
1809 : fileName, loop, startPosition, volumeScaling, notificationTime,
1810 0 : stopPosition, (const CodecInst*)codecInst) != 0) {
1811 0 : _engineStatisticsPtr->SetLastError(
1812 : VE_BAD_FILE, kTraceError,
1813 0 : "StartPlayingFile() failed to start file playout");
1814 0 : output_file_player_->StopPlayingFile();
1815 0 : output_file_player_.reset();
1816 0 : return -1;
1817 : }
1818 0 : output_file_player_->RegisterModuleFileCallback(this);
1819 0 : channel_state_.SetOutputFilePlaying(true);
1820 : }
1821 :
1822 0 : if (RegisterFilePlayingToMixer() != 0)
1823 0 : return -1;
1824 :
1825 0 : return 0;
1826 : }
1827 :
1828 0 : int Channel::StartPlayingFileLocally(InStream* stream,
1829 : FileFormats format,
1830 : int startPosition,
1831 : float volumeScaling,
1832 : int stopPosition,
1833 : const CodecInst* codecInst) {
1834 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1835 : "Channel::StartPlayingFileLocally(format=%d,"
1836 : " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
1837 : format, volumeScaling, startPosition, stopPosition);
1838 :
1839 0 : if (stream == NULL) {
1840 0 : _engineStatisticsPtr->SetLastError(
1841 : VE_BAD_FILE, kTraceError,
1842 0 : "StartPlayingFileLocally() NULL as input stream");
1843 0 : return -1;
1844 : }
1845 :
1846 0 : if (channel_state_.Get().output_file_playing) {
1847 0 : _engineStatisticsPtr->SetLastError(
1848 : VE_ALREADY_PLAYING, kTraceError,
1849 0 : "StartPlayingFileLocally() is already playing");
1850 0 : return -1;
1851 : }
1852 :
1853 : {
1854 0 : rtc::CritScope cs(&_fileCritSect);
1855 :
1856 : // Destroy the old instance
1857 0 : if (output_file_player_) {
1858 0 : output_file_player_->RegisterModuleFileCallback(NULL);
1859 0 : output_file_player_.reset();
1860 : }
1861 :
1862 : // Create the instance
1863 0 : output_file_player_ = FilePlayer::CreateFilePlayer(
1864 0 : _outputFilePlayerId, (const FileFormats)format);
1865 :
1866 0 : if (!output_file_player_) {
1867 0 : _engineStatisticsPtr->SetLastError(
1868 : VE_INVALID_ARGUMENT, kTraceError,
1869 0 : "StartPlayingFileLocally() filePlayer format isnot correct");
1870 0 : return -1;
1871 : }
1872 :
1873 0 : const uint32_t notificationTime(0);
1874 :
1875 0 : if (output_file_player_->StartPlayingFile(stream, startPosition,
1876 : volumeScaling, notificationTime,
1877 0 : stopPosition, codecInst) != 0) {
1878 0 : _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
1879 : "StartPlayingFile() failed to "
1880 0 : "start file playout");
1881 0 : output_file_player_->StopPlayingFile();
1882 0 : output_file_player_.reset();
1883 0 : return -1;
1884 : }
1885 0 : output_file_player_->RegisterModuleFileCallback(this);
1886 0 : channel_state_.SetOutputFilePlaying(true);
1887 : }
1888 :
1889 0 : if (RegisterFilePlayingToMixer() != 0)
1890 0 : return -1;
1891 :
1892 0 : return 0;
1893 : }
1894 :
1895 0 : int Channel::StopPlayingFileLocally() {
1896 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1897 : "Channel::StopPlayingFileLocally()");
1898 :
1899 0 : if (!channel_state_.Get().output_file_playing) {
1900 0 : return 0;
1901 : }
1902 :
1903 : {
1904 0 : rtc::CritScope cs(&_fileCritSect);
1905 :
1906 0 : if (output_file_player_->StopPlayingFile() != 0) {
1907 0 : _engineStatisticsPtr->SetLastError(
1908 : VE_STOP_RECORDING_FAILED, kTraceError,
1909 0 : "StopPlayingFile() could not stop playing");
1910 0 : return -1;
1911 : }
1912 0 : output_file_player_->RegisterModuleFileCallback(NULL);
1913 0 : output_file_player_.reset();
1914 0 : channel_state_.SetOutputFilePlaying(false);
1915 : }
1916 : // _fileCritSect cannot be taken while calling
1917 : // SetAnonymousMixibilityStatus. Refer to comments in
1918 : // StartPlayingFileLocally(const char* ...) for more details.
1919 0 : if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0) {
1920 0 : _engineStatisticsPtr->SetLastError(
1921 : VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1922 : "StopPlayingFile() failed to stop participant from playing as"
1923 0 : "file in the mixer");
1924 0 : return -1;
1925 : }
1926 :
1927 0 : return 0;
1928 : }
1929 :
1930 0 : int Channel::IsPlayingFileLocally() const {
1931 0 : return channel_state_.Get().output_file_playing;
1932 : }
1933 :
1934 0 : int Channel::RegisterFilePlayingToMixer() {
1935 : // Return success for not registering for file playing to mixer if:
1936 : // 1. playing file before playout is started on that channel.
1937 : // 2. starting playout without file playing on that channel.
1938 0 : if (!channel_state_.Get().playing ||
1939 0 : !channel_state_.Get().output_file_playing) {
1940 0 : return 0;
1941 : }
1942 :
1943 : // |_fileCritSect| cannot be taken while calling
1944 : // SetAnonymousMixabilityStatus() since as soon as the participant is added
1945 : // frames can be pulled by the mixer. Since the frames are generated from
1946 : // the file, _fileCritSect will be taken. This would result in a deadlock.
1947 0 : if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0) {
1948 0 : channel_state_.SetOutputFilePlaying(false);
1949 0 : rtc::CritScope cs(&_fileCritSect);
1950 0 : _engineStatisticsPtr->SetLastError(
1951 : VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1952 0 : "StartPlayingFile() failed to add participant as file to mixer");
1953 0 : output_file_player_->StopPlayingFile();
1954 0 : output_file_player_.reset();
1955 0 : return -1;
1956 : }
1957 :
1958 0 : return 0;
1959 : }
1960 :
1961 0 : int Channel::StartPlayingFileAsMicrophone(const char* fileName,
1962 : bool loop,
1963 : FileFormats format,
1964 : int startPosition,
1965 : float volumeScaling,
1966 : int stopPosition,
1967 : const CodecInst* codecInst) {
1968 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1969 : "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
1970 : "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
1971 : "stopPosition=%d)",
1972 : fileName, loop, format, volumeScaling, startPosition,
1973 : stopPosition);
1974 :
1975 0 : rtc::CritScope cs(&_fileCritSect);
1976 :
1977 0 : if (channel_state_.Get().input_file_playing) {
1978 0 : _engineStatisticsPtr->SetLastError(
1979 : VE_ALREADY_PLAYING, kTraceWarning,
1980 0 : "StartPlayingFileAsMicrophone() filePlayer is playing");
1981 0 : return 0;
1982 : }
1983 :
1984 : // Destroy the old instance
1985 0 : if (input_file_player_) {
1986 0 : input_file_player_->RegisterModuleFileCallback(NULL);
1987 0 : input_file_player_.reset();
1988 : }
1989 :
1990 : // Create the instance
1991 0 : input_file_player_ = FilePlayer::CreateFilePlayer(_inputFilePlayerId,
1992 0 : (const FileFormats)format);
1993 :
1994 0 : if (!input_file_player_) {
1995 0 : _engineStatisticsPtr->SetLastError(
1996 : VE_INVALID_ARGUMENT, kTraceError,
1997 0 : "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
1998 0 : return -1;
1999 : }
2000 :
2001 0 : const uint32_t notificationTime(0);
2002 :
2003 0 : if (input_file_player_->StartPlayingFile(
2004 : fileName, loop, startPosition, volumeScaling, notificationTime,
2005 0 : stopPosition, (const CodecInst*)codecInst) != 0) {
2006 0 : _engineStatisticsPtr->SetLastError(
2007 : VE_BAD_FILE, kTraceError,
2008 0 : "StartPlayingFile() failed to start file playout");
2009 0 : input_file_player_->StopPlayingFile();
2010 0 : input_file_player_.reset();
2011 0 : return -1;
2012 : }
2013 0 : input_file_player_->RegisterModuleFileCallback(this);
2014 0 : channel_state_.SetInputFilePlaying(true);
2015 :
2016 0 : return 0;
2017 : }
2018 :
2019 0 : int Channel::StartPlayingFileAsMicrophone(InStream* stream,
2020 : FileFormats format,
2021 : int startPosition,
2022 : float volumeScaling,
2023 : int stopPosition,
2024 : const CodecInst* codecInst) {
2025 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2026 : "Channel::StartPlayingFileAsMicrophone(format=%d, "
2027 : "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
2028 : format, volumeScaling, startPosition, stopPosition);
2029 :
2030 0 : if (stream == NULL) {
2031 0 : _engineStatisticsPtr->SetLastError(
2032 : VE_BAD_FILE, kTraceError,
2033 0 : "StartPlayingFileAsMicrophone NULL as input stream");
2034 0 : return -1;
2035 : }
2036 :
2037 0 : rtc::CritScope cs(&_fileCritSect);
2038 :
2039 0 : if (channel_state_.Get().input_file_playing) {
2040 0 : _engineStatisticsPtr->SetLastError(
2041 : VE_ALREADY_PLAYING, kTraceWarning,
2042 0 : "StartPlayingFileAsMicrophone() is playing");
2043 0 : return 0;
2044 : }
2045 :
2046 : // Destroy the old instance
2047 0 : if (input_file_player_) {
2048 0 : input_file_player_->RegisterModuleFileCallback(NULL);
2049 0 : input_file_player_.reset();
2050 : }
2051 :
2052 : // Create the instance
2053 0 : input_file_player_ = FilePlayer::CreateFilePlayer(_inputFilePlayerId,
2054 0 : (const FileFormats)format);
2055 :
2056 0 : if (!input_file_player_) {
2057 0 : _engineStatisticsPtr->SetLastError(
2058 : VE_INVALID_ARGUMENT, kTraceError,
2059 0 : "StartPlayingInputFile() filePlayer format isnot correct");
2060 0 : return -1;
2061 : }
2062 :
2063 0 : const uint32_t notificationTime(0);
2064 :
2065 0 : if (input_file_player_->StartPlayingFile(stream, startPosition, volumeScaling,
2066 : notificationTime, stopPosition,
2067 0 : codecInst) != 0) {
2068 0 : _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2069 : "StartPlayingFile() failed to start "
2070 0 : "file playout");
2071 0 : input_file_player_->StopPlayingFile();
2072 0 : input_file_player_.reset();
2073 0 : return -1;
2074 : }
2075 :
2076 0 : input_file_player_->RegisterModuleFileCallback(this);
2077 0 : channel_state_.SetInputFilePlaying(true);
2078 :
2079 0 : return 0;
2080 : }
2081 :
2082 0 : int Channel::StopPlayingFileAsMicrophone() {
2083 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2084 : "Channel::StopPlayingFileAsMicrophone()");
2085 :
2086 0 : rtc::CritScope cs(&_fileCritSect);
2087 :
2088 0 : if (!channel_state_.Get().input_file_playing) {
2089 0 : return 0;
2090 : }
2091 :
2092 0 : if (input_file_player_->StopPlayingFile() != 0) {
2093 0 : _engineStatisticsPtr->SetLastError(
2094 : VE_STOP_RECORDING_FAILED, kTraceError,
2095 0 : "StopPlayingFile() could not stop playing");
2096 0 : return -1;
2097 : }
2098 0 : input_file_player_->RegisterModuleFileCallback(NULL);
2099 0 : input_file_player_.reset();
2100 0 : channel_state_.SetInputFilePlaying(false);
2101 :
2102 0 : return 0;
2103 : }
2104 :
2105 0 : int Channel::IsPlayingFileAsMicrophone() const {
2106 0 : return channel_state_.Get().input_file_playing;
2107 : }
2108 :
2109 0 : int Channel::StartRecordingPlayout(const char* fileName,
2110 : const CodecInst* codecInst) {
2111 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2112 : "Channel::StartRecordingPlayout(fileName=%s)", fileName);
2113 :
2114 0 : if (_outputFileRecording) {
2115 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
2116 : "StartRecordingPlayout() is already recording");
2117 0 : return 0;
2118 : }
2119 :
2120 : FileFormats format;
2121 0 : const uint32_t notificationTime(0); // Not supported in VoE
2122 0 : CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
2123 :
2124 0 : if ((codecInst != NULL) &&
2125 0 : ((codecInst->channels < 1) || (codecInst->channels > 2))) {
2126 0 : _engineStatisticsPtr->SetLastError(
2127 : VE_BAD_ARGUMENT, kTraceError,
2128 0 : "StartRecordingPlayout() invalid compression");
2129 0 : return (-1);
2130 : }
2131 0 : if (codecInst == NULL) {
2132 0 : format = kFileFormatPcm16kHzFile;
2133 0 : codecInst = &dummyCodec;
2134 0 : } else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
2135 0 : (STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
2136 0 : (STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
2137 0 : format = kFileFormatWavFile;
2138 : } else {
2139 0 : format = kFileFormatCompressedFile;
2140 : }
2141 :
2142 0 : rtc::CritScope cs(&_fileCritSect);
2143 :
2144 : // Destroy the old instance
2145 0 : if (output_file_recorder_) {
2146 0 : output_file_recorder_->RegisterModuleFileCallback(NULL);
2147 0 : output_file_recorder_.reset();
2148 : }
2149 :
2150 0 : output_file_recorder_ = FileRecorder::CreateFileRecorder(
2151 0 : _outputFileRecorderId, (const FileFormats)format);
2152 0 : if (!output_file_recorder_) {
2153 0 : _engineStatisticsPtr->SetLastError(
2154 : VE_INVALID_ARGUMENT, kTraceError,
2155 0 : "StartRecordingPlayout() fileRecorder format isnot correct");
2156 0 : return -1;
2157 : }
2158 :
2159 0 : if (output_file_recorder_->StartRecordingAudioFile(
2160 0 : fileName, (const CodecInst&)*codecInst, notificationTime) != 0) {
2161 0 : _engineStatisticsPtr->SetLastError(
2162 : VE_BAD_FILE, kTraceError,
2163 0 : "StartRecordingAudioFile() failed to start file recording");
2164 0 : output_file_recorder_->StopRecording();
2165 0 : output_file_recorder_.reset();
2166 0 : return -1;
2167 : }
2168 0 : output_file_recorder_->RegisterModuleFileCallback(this);
2169 0 : _outputFileRecording = true;
2170 :
2171 0 : return 0;
2172 : }
2173 :
2174 0 : int Channel::StartRecordingPlayout(OutStream* stream,
2175 : const CodecInst* codecInst) {
2176 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2177 : "Channel::StartRecordingPlayout()");
2178 :
2179 0 : if (_outputFileRecording) {
2180 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
2181 : "StartRecordingPlayout() is already recording");
2182 0 : return 0;
2183 : }
2184 :
2185 : FileFormats format;
2186 0 : const uint32_t notificationTime(0); // Not supported in VoE
2187 0 : CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
2188 :
2189 0 : if (codecInst != NULL && codecInst->channels != 1) {
2190 0 : _engineStatisticsPtr->SetLastError(
2191 : VE_BAD_ARGUMENT, kTraceError,
2192 0 : "StartRecordingPlayout() invalid compression");
2193 0 : return (-1);
2194 : }
2195 0 : if (codecInst == NULL) {
2196 0 : format = kFileFormatPcm16kHzFile;
2197 0 : codecInst = &dummyCodec;
2198 0 : } else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
2199 0 : (STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
2200 0 : (STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
2201 0 : format = kFileFormatWavFile;
2202 : } else {
2203 0 : format = kFileFormatCompressedFile;
2204 : }
2205 :
2206 0 : rtc::CritScope cs(&_fileCritSect);
2207 :
2208 : // Destroy the old instance
2209 0 : if (output_file_recorder_) {
2210 0 : output_file_recorder_->RegisterModuleFileCallback(NULL);
2211 0 : output_file_recorder_.reset();
2212 : }
2213 :
2214 0 : output_file_recorder_ = FileRecorder::CreateFileRecorder(
2215 0 : _outputFileRecorderId, (const FileFormats)format);
2216 0 : if (!output_file_recorder_) {
2217 0 : _engineStatisticsPtr->SetLastError(
2218 : VE_INVALID_ARGUMENT, kTraceError,
2219 0 : "StartRecordingPlayout() fileRecorder format isnot correct");
2220 0 : return -1;
2221 : }
2222 :
2223 0 : if (output_file_recorder_->StartRecordingAudioFile(stream, *codecInst,
2224 0 : notificationTime) != 0) {
2225 0 : _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2226 : "StartRecordingPlayout() failed to "
2227 0 : "start file recording");
2228 0 : output_file_recorder_->StopRecording();
2229 0 : output_file_recorder_.reset();
2230 0 : return -1;
2231 : }
2232 :
2233 0 : output_file_recorder_->RegisterModuleFileCallback(this);
2234 0 : _outputFileRecording = true;
2235 :
2236 0 : return 0;
2237 : }
2238 :
2239 0 : int Channel::StopRecordingPlayout() {
2240 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
2241 : "Channel::StopRecordingPlayout()");
2242 :
2243 0 : if (!_outputFileRecording) {
2244 : WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1),
2245 : "StopRecordingPlayout() isnot recording");
2246 0 : return -1;
2247 : }
2248 :
2249 0 : rtc::CritScope cs(&_fileCritSect);
2250 :
2251 0 : if (output_file_recorder_->StopRecording() != 0) {
2252 0 : _engineStatisticsPtr->SetLastError(
2253 : VE_STOP_RECORDING_FAILED, kTraceError,
2254 0 : "StopRecording() could not stop recording");
2255 0 : return (-1);
2256 : }
2257 0 : output_file_recorder_->RegisterModuleFileCallback(NULL);
2258 0 : output_file_recorder_.reset();
2259 0 : _outputFileRecording = false;
2260 :
2261 0 : return 0;
2262 : }
2263 :
2264 0 : void Channel::SetMixWithMicStatus(bool mix) {
2265 0 : rtc::CritScope cs(&_fileCritSect);
2266 0 : _mixFileWithMicrophone = mix;
2267 0 : }
2268 :
2269 0 : int Channel::GetSpeechOutputLevel(uint32_t& level) const {
2270 0 : int8_t currentLevel = _outputAudioLevel.Level();
2271 0 : level = static_cast<int32_t>(currentLevel);
2272 0 : return 0;
2273 : }
2274 :
2275 0 : int Channel::GetSpeechOutputLevelFullRange(uint32_t& level) const {
2276 0 : int16_t currentLevel = _outputAudioLevel.LevelFullRange();
2277 0 : level = static_cast<int32_t>(currentLevel);
2278 0 : return 0;
2279 : }
2280 :
2281 0 : int Channel::SetInputMute(bool enable) {
2282 0 : rtc::CritScope cs(&volume_settings_critsect_);
2283 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2284 : "Channel::SetMute(enable=%d)", enable);
2285 0 : input_mute_ = enable;
2286 0 : return 0;
2287 : }
2288 :
2289 0 : bool Channel::InputMute() const {
2290 0 : rtc::CritScope cs(&volume_settings_critsect_);
2291 0 : return input_mute_;
2292 : }
2293 :
2294 0 : int Channel::SetOutputVolumePan(float left, float right) {
2295 0 : rtc::CritScope cs(&volume_settings_critsect_);
2296 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2297 : "Channel::SetOutputVolumePan()");
2298 0 : _panLeft = left;
2299 0 : _panRight = right;
2300 0 : return 0;
2301 : }
2302 :
2303 0 : int Channel::GetOutputVolumePan(float& left, float& right) const {
2304 0 : rtc::CritScope cs(&volume_settings_critsect_);
2305 0 : left = _panLeft;
2306 0 : right = _panRight;
2307 0 : return 0;
2308 : }
2309 :
2310 0 : int Channel::SetChannelOutputVolumeScaling(float scaling) {
2311 0 : rtc::CritScope cs(&volume_settings_critsect_);
2312 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2313 : "Channel::SetChannelOutputVolumeScaling()");
2314 0 : _outputGain = scaling;
2315 0 : return 0;
2316 : }
2317 :
2318 0 : int Channel::GetChannelOutputVolumeScaling(float& scaling) const {
2319 0 : rtc::CritScope cs(&volume_settings_critsect_);
2320 0 : scaling = _outputGain;
2321 0 : return 0;
2322 : }
2323 :
2324 0 : int Channel::SendTelephoneEventOutband(int event, int duration_ms) {
2325 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2326 : "Channel::SendTelephoneEventOutband(...)");
2327 0 : RTC_DCHECK_LE(0, event);
2328 0 : RTC_DCHECK_GE(255, event);
2329 0 : RTC_DCHECK_LE(0, duration_ms);
2330 0 : RTC_DCHECK_GE(65535, duration_ms);
2331 0 : if (!Sending()) {
2332 0 : return -1;
2333 : }
2334 0 : if (_rtpRtcpModule->SendTelephoneEventOutband(
2335 0 : event, duration_ms, kTelephoneEventAttenuationdB) != 0) {
2336 0 : _engineStatisticsPtr->SetLastError(
2337 : VE_SEND_DTMF_FAILED, kTraceWarning,
2338 0 : "SendTelephoneEventOutband() failed to send event");
2339 0 : return -1;
2340 : }
2341 0 : return 0;
2342 : }
2343 :
2344 0 : int Channel::SetSendTelephoneEventPayloadType(int payload_type,
2345 : int payload_frequency) {
2346 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2347 : "Channel::SetSendTelephoneEventPayloadType()");
2348 0 : RTC_DCHECK_LE(0, payload_type);
2349 0 : RTC_DCHECK_GE(127, payload_type);
2350 0 : CodecInst codec = {0};
2351 0 : codec.pltype = payload_type;
2352 0 : codec.plfreq = payload_frequency;
2353 0 : memcpy(codec.plname, "telephone-event", 16);
2354 0 : if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
2355 0 : _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
2356 0 : if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
2357 0 : _engineStatisticsPtr->SetLastError(
2358 : VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2359 : "SetSendTelephoneEventPayloadType() failed to register send"
2360 0 : "payload type");
2361 0 : return -1;
2362 : }
2363 : }
2364 0 : return 0;
2365 : }
2366 :
2367 0 : int Channel::VoiceActivityIndicator(int& activity) {
2368 0 : activity = _sendFrameType;
2369 0 : return 0;
2370 : }
2371 :
2372 0 : int Channel::SetLocalSSRC(unsigned int ssrc) {
2373 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2374 : "Channel::SetLocalSSRC()");
2375 0 : if (channel_state_.Get().sending) {
2376 0 : _engineStatisticsPtr->SetLastError(VE_ALREADY_SENDING, kTraceError,
2377 0 : "SetLocalSSRC() already sending");
2378 0 : return -1;
2379 : }
2380 0 : _rtpRtcpModule->SetSSRC(ssrc);
2381 0 : return 0;
2382 : }
2383 :
2384 0 : int Channel::GetLocalSSRC(unsigned int& ssrc) {
2385 0 : ssrc = _rtpRtcpModule->SSRC();
2386 0 : return 0;
2387 : }
2388 :
2389 0 : int Channel::GetRemoteSSRC(unsigned int& ssrc) {
2390 0 : ssrc = rtp_receiver_->SSRC();
2391 0 : return 0;
2392 : }
2393 :
2394 0 : int Channel::SetSendAudioLevelIndicationStatus(bool enable, unsigned char id) {
2395 0 : _includeAudioLevelIndication = enable;
2396 0 : return SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id);
2397 : }
2398 :
2399 0 : int Channel::SetReceiveAudioLevelIndicationStatus(bool enable,
2400 : unsigned char id) {
2401 0 : rtp_header_parser_->DeregisterRtpHeaderExtension(kRtpExtensionAudioLevel);
2402 0 : if (enable &&
2403 0 : !rtp_header_parser_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
2404 0 : id)) {
2405 0 : return -1;
2406 : }
2407 0 : return 0;
2408 : }
2409 :
2410 0 : void Channel::EnableSendTransportSequenceNumber(int id) {
2411 : int ret =
2412 0 : SetSendRtpHeaderExtension(true, kRtpExtensionTransportSequenceNumber, id);
2413 0 : RTC_DCHECK_EQ(0, ret);
2414 0 : }
2415 :
2416 0 : void Channel::EnableReceiveTransportSequenceNumber(int id) {
2417 0 : rtp_header_parser_->DeregisterRtpHeaderExtension(
2418 0 : kRtpExtensionTransportSequenceNumber);
2419 0 : bool ret = rtp_header_parser_->RegisterRtpHeaderExtension(
2420 0 : kRtpExtensionTransportSequenceNumber, id);
2421 0 : RTC_DCHECK(ret);
2422 0 : }
2423 :
2424 0 : void Channel::RegisterSenderCongestionControlObjects(
2425 : RtpPacketSender* rtp_packet_sender,
2426 : TransportFeedbackObserver* transport_feedback_observer,
2427 : PacketRouter* packet_router) {
2428 0 : RTC_DCHECK(rtp_packet_sender);
2429 0 : RTC_DCHECK(transport_feedback_observer);
2430 0 : RTC_DCHECK(packet_router && !packet_router_);
2431 0 : feedback_observer_proxy_->SetTransportFeedbackObserver(
2432 0 : transport_feedback_observer);
2433 0 : seq_num_allocator_proxy_->SetSequenceNumberAllocator(packet_router);
2434 0 : rtp_packet_sender_proxy_->SetPacketSender(rtp_packet_sender);
2435 0 : _rtpRtcpModule->SetStorePacketsStatus(true, 600);
2436 0 : packet_router->AddRtpModule(_rtpRtcpModule.get());
2437 0 : packet_router_ = packet_router;
2438 0 : }
2439 :
2440 0 : void Channel::RegisterReceiverCongestionControlObjects(
2441 : PacketRouter* packet_router) {
2442 0 : RTC_DCHECK(packet_router && !packet_router_);
2443 0 : packet_router->AddRtpModule(_rtpRtcpModule.get());
2444 0 : packet_router_ = packet_router;
2445 0 : }
2446 :
2447 0 : void Channel::ResetCongestionControlObjects() {
2448 0 : RTC_DCHECK(packet_router_);
2449 0 : _rtpRtcpModule->SetStorePacketsStatus(false, 600);
2450 0 : feedback_observer_proxy_->SetTransportFeedbackObserver(nullptr);
2451 0 : seq_num_allocator_proxy_->SetSequenceNumberAllocator(nullptr);
2452 0 : packet_router_->RemoveRtpModule(_rtpRtcpModule.get());
2453 0 : packet_router_ = nullptr;
2454 0 : rtp_packet_sender_proxy_->SetPacketSender(nullptr);
2455 0 : }
2456 :
2457 0 : void Channel::SetRTCPStatus(bool enable) {
2458 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2459 : "Channel::SetRTCPStatus()");
2460 0 : _rtpRtcpModule->SetRTCPStatus(enable ? RtcpMode::kCompound : RtcpMode::kOff);
2461 0 : }
2462 :
2463 0 : int Channel::GetRTCPStatus(bool& enabled) {
2464 0 : RtcpMode method = _rtpRtcpModule->RTCP();
2465 0 : enabled = (method != RtcpMode::kOff);
2466 0 : return 0;
2467 : }
2468 :
2469 0 : int Channel::SetRTCP_CNAME(const char cName[256]) {
2470 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2471 : "Channel::SetRTCP_CNAME()");
2472 0 : if (_rtpRtcpModule->SetCNAME(cName) != 0) {
2473 0 : _engineStatisticsPtr->SetLastError(
2474 : VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2475 0 : "SetRTCP_CNAME() failed to set RTCP CNAME");
2476 0 : return -1;
2477 : }
2478 0 : return 0;
2479 : }
2480 :
2481 0 : int Channel::GetRemoteRTCP_CNAME(char cName[256]) {
2482 0 : if (cName == NULL) {
2483 0 : _engineStatisticsPtr->SetLastError(
2484 : VE_INVALID_ARGUMENT, kTraceError,
2485 0 : "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
2486 0 : return -1;
2487 : }
2488 : char cname[RTCP_CNAME_SIZE];
2489 0 : const uint32_t remoteSSRC = rtp_receiver_->SSRC();
2490 0 : if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0) {
2491 0 : _engineStatisticsPtr->SetLastError(
2492 : VE_CANNOT_RETRIEVE_CNAME, kTraceError,
2493 0 : "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
2494 0 : return -1;
2495 : }
2496 0 : strcpy(cName, cname);
2497 0 : return 0;
2498 : }
2499 :
2500 0 : int Channel::GetRemoteRTCPData(unsigned int& NTPHigh,
2501 : unsigned int& NTPLow,
2502 : unsigned int& timestamp,
2503 : unsigned int& playoutTimestamp,
2504 : unsigned int* jitter,
2505 : unsigned short* fractionLost) {
2506 : // --- Information from sender info in received Sender Reports
2507 :
2508 : RTCPSenderInfo senderInfo;
2509 0 : if (_rtpRtcpModule->RemoteRTCPStat(&senderInfo) != 0) {
2510 0 : _engineStatisticsPtr->SetLastError(
2511 : VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2512 : "GetRemoteRTCPData() failed to retrieve sender info for remote "
2513 0 : "side");
2514 0 : return -1;
2515 : }
2516 :
2517 : // We only utilize 12 out of 20 bytes in the sender info (ignores packet
2518 : // and octet count)
2519 0 : NTPHigh = senderInfo.NTPseconds;
2520 0 : NTPLow = senderInfo.NTPfraction;
2521 0 : timestamp = senderInfo.RTPtimeStamp;
2522 :
2523 : // --- Locally derived information
2524 :
2525 : // This value is updated on each incoming RTCP packet (0 when no packet
2526 : // has been received)
2527 0 : playoutTimestamp = playout_timestamp_rtcp_;
2528 :
2529 0 : if (NULL != jitter || NULL != fractionLost) {
2530 : // Get all RTCP receiver report blocks that have been received on this
2531 : // channel. If we receive RTP packets from a remote source we know the
2532 : // remote SSRC and use the report block from him.
2533 : // Otherwise use the first report block.
2534 0 : std::vector<RTCPReportBlock> remote_stats;
2535 0 : if (_rtpRtcpModule->RemoteRTCPStat(&remote_stats) != 0 ||
2536 0 : remote_stats.empty()) {
2537 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2538 : "GetRemoteRTCPData() failed to measure statistics due"
2539 : " to lack of received RTP and/or RTCP packets");
2540 0 : return -1;
2541 : }
2542 :
2543 0 : uint32_t remoteSSRC = rtp_receiver_->SSRC();
2544 0 : std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin();
2545 0 : for (; it != remote_stats.end(); ++it) {
2546 0 : if (it->remoteSSRC == remoteSSRC)
2547 0 : break;
2548 : }
2549 :
2550 0 : if (it == remote_stats.end()) {
2551 : // If we have not received any RTCP packets from this SSRC it probably
2552 : // means that we have not received any RTP packets.
2553 : // Use the first received report block instead.
2554 0 : it = remote_stats.begin();
2555 0 : remoteSSRC = it->remoteSSRC;
2556 : }
2557 :
2558 0 : if (jitter) {
2559 0 : *jitter = it->jitter;
2560 : }
2561 :
2562 0 : if (fractionLost) {
2563 0 : *fractionLost = it->fractionLost;
2564 : }
2565 : }
2566 0 : return 0;
2567 : }
2568 :
2569 0 : int Channel::SendApplicationDefinedRTCPPacket(
2570 : unsigned char subType,
2571 : unsigned int name,
2572 : const char* data,
2573 : unsigned short dataLengthInBytes) {
2574 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2575 : "Channel::SendApplicationDefinedRTCPPacket()");
2576 0 : if (!channel_state_.Get().sending) {
2577 0 : _engineStatisticsPtr->SetLastError(
2578 : VE_NOT_SENDING, kTraceError,
2579 0 : "SendApplicationDefinedRTCPPacket() not sending");
2580 0 : return -1;
2581 : }
2582 0 : if (NULL == data) {
2583 0 : _engineStatisticsPtr->SetLastError(
2584 : VE_INVALID_ARGUMENT, kTraceError,
2585 0 : "SendApplicationDefinedRTCPPacket() invalid data value");
2586 0 : return -1;
2587 : }
2588 0 : if (dataLengthInBytes % 4 != 0) {
2589 0 : _engineStatisticsPtr->SetLastError(
2590 : VE_INVALID_ARGUMENT, kTraceError,
2591 0 : "SendApplicationDefinedRTCPPacket() invalid length value");
2592 0 : return -1;
2593 : }
2594 0 : RtcpMode status = _rtpRtcpModule->RTCP();
2595 0 : if (status == RtcpMode::kOff) {
2596 0 : _engineStatisticsPtr->SetLastError(
2597 : VE_RTCP_ERROR, kTraceError,
2598 0 : "SendApplicationDefinedRTCPPacket() RTCP is disabled");
2599 0 : return -1;
2600 : }
2601 :
2602 : // Create and schedule the RTCP APP packet for transmission
2603 0 : if (_rtpRtcpModule->SetRTCPApplicationSpecificData(
2604 0 : subType, name, (const unsigned char*)data, dataLengthInBytes) != 0) {
2605 0 : _engineStatisticsPtr->SetLastError(
2606 : VE_SEND_ERROR, kTraceError,
2607 0 : "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
2608 0 : return -1;
2609 : }
2610 0 : return 0;
2611 : }
2612 :
2613 0 : int Channel::GetRTPStatistics(unsigned int& averageJitterMs,
2614 : unsigned int& maxJitterMs,
2615 : unsigned int& discardedPackets,
2616 : unsigned int& cumulativeLost) {
2617 : // The jitter statistics is updated for each received RTP packet and is
2618 : // based on received packets.
2619 0 : if (_rtpRtcpModule->RTCP() == RtcpMode::kOff) {
2620 : // If RTCP is off, there is no timed thread in the RTCP module regularly
2621 : // generating new stats, trigger the update manually here instead.
2622 : StreamStatistician* statistician =
2623 0 : rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
2624 0 : if (statistician) {
2625 : // Don't use returned statistics, use data from proxy instead so that
2626 : // max jitter can be fetched atomically.
2627 0 : RtcpStatistics s;
2628 0 : statistician->GetStatistics(&s, true);
2629 : }
2630 : }
2631 :
2632 0 : ChannelStatistics stats = statistics_proxy_->GetStats();
2633 0 : const int32_t playoutFrequency = audio_coding_->PlayoutFrequency();
2634 0 : if (playoutFrequency > 0) {
2635 : // Scale RTP statistics given the current playout frequency
2636 0 : maxJitterMs = stats.max_jitter / (playoutFrequency / 1000);
2637 0 : averageJitterMs = stats.rtcp.jitter / (playoutFrequency / 1000);
2638 0 : cumulativeLost = stats.rtcp.cumulative_lost;
2639 : }
2640 :
2641 0 : discardedPackets = _numberOfDiscardedPackets;
2642 :
2643 0 : return 0;
2644 : }
2645 :
2646 0 : int Channel::GetRemoteRTCPReportBlocks(
2647 : std::vector<ReportBlock>* report_blocks) {
2648 0 : if (report_blocks == NULL) {
2649 0 : _engineStatisticsPtr->SetLastError(
2650 : VE_INVALID_ARGUMENT, kTraceError,
2651 0 : "GetRemoteRTCPReportBlock()s invalid report_blocks.");
2652 0 : return -1;
2653 : }
2654 :
2655 : // Get the report blocks from the latest received RTCP Sender or Receiver
2656 : // Report. Each element in the vector contains the sender's SSRC and a
2657 : // report block according to RFC 3550.
2658 0 : std::vector<RTCPReportBlock> rtcp_report_blocks;
2659 0 : if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) {
2660 0 : return -1;
2661 : }
2662 :
2663 0 : if (rtcp_report_blocks.empty())
2664 0 : return 0;
2665 :
2666 0 : std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
2667 0 : for (; it != rtcp_report_blocks.end(); ++it) {
2668 : ReportBlock report_block;
2669 0 : report_block.sender_SSRC = it->remoteSSRC;
2670 0 : report_block.source_SSRC = it->sourceSSRC;
2671 0 : report_block.fraction_lost = it->fractionLost;
2672 0 : report_block.cumulative_num_packets_lost = it->cumulativeLost;
2673 0 : report_block.extended_highest_sequence_number = it->extendedHighSeqNum;
2674 0 : report_block.interarrival_jitter = it->jitter;
2675 0 : report_block.last_SR_timestamp = it->lastSR;
2676 0 : report_block.delay_since_last_SR = it->delaySinceLastSR;
2677 0 : report_blocks->push_back(report_block);
2678 : }
2679 0 : return 0;
2680 : }
2681 :
2682 0 : int Channel::GetRTPStatistics(CallStatistics& stats) {
2683 : // --- RtcpStatistics
2684 : // GetStatistics() grabs the stream_lock_ inside the object
2685 : // rtp_receiver_->SSRC grabs a lock too.
2686 :
2687 : // The jitter statistics is updated for each received RTP packet and is
2688 : // based on received packets.
2689 0 : RtcpStatistics statistics;
2690 : StreamStatistician* statistician =
2691 0 : rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
2692 0 : if (statistician) {
2693 0 : statistician->GetStatistics(&statistics,
2694 0 : _rtpRtcpModule->RTCP() == RtcpMode::kOff);
2695 : }
2696 :
2697 0 : stats.fractionLost = statistics.fraction_lost;
2698 0 : stats.cumulativeLost = statistics.cumulative_lost;
2699 0 : stats.extendedMax = statistics.extended_max_sequence_number;
2700 0 : stats.jitterSamples = statistics.jitter;
2701 :
2702 : // --- RTT
2703 0 : stats.rttMs = GetRTT(true);
2704 :
2705 : // --- Data counters
2706 :
2707 0 : size_t bytesSent(0);
2708 0 : uint32_t packetsSent(0);
2709 0 : size_t bytesReceived(0);
2710 0 : uint32_t packetsReceived(0);
2711 :
2712 0 : if (statistician) {
2713 0 : statistician->GetDataCounters(&bytesReceived, &packetsReceived);
2714 : }
2715 :
2716 0 : if (_rtpRtcpModule->DataCountersRTP(&bytesSent, &packetsSent) != 0) {
2717 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2718 : "GetRTPStatistics() failed to retrieve RTP datacounters =>"
2719 : " output will not be complete");
2720 : }
2721 :
2722 0 : stats.bytesSent = bytesSent;
2723 0 : stats.packetsSent = packetsSent;
2724 0 : stats.bytesReceived = bytesReceived;
2725 0 : stats.packetsReceived = packetsReceived;
2726 :
2727 : // --- Timestamps
2728 : {
2729 0 : rtc::CritScope lock(&ts_stats_lock_);
2730 0 : stats.capture_start_ntp_time_ms_ = capture_start_ntp_time_ms_;
2731 : }
2732 0 : return 0;
2733 : }
2734 :
2735 0 : int Channel::GetRTCPPacketTypeCounters(RtcpPacketTypeCounter& stats) {
2736 0 : if (_rtpRtcpModule->RTCP() == RtcpMode::kOff) {
2737 0 : return -1;
2738 : }
2739 0 : statistics_proxy_->GetPacketTypeCounter(stats);
2740 0 : return 0;
2741 : }
2742 :
2743 0 : int Channel::SetCodecFECStatus(bool enable) {
2744 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2745 : "Channel::SetCodecFECStatus()");
2746 :
2747 0 : if (!codec_manager_.SetCodecFEC(enable) ||
2748 0 : !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
2749 0 : _engineStatisticsPtr->SetLastError(
2750 : VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2751 0 : "SetCodecFECStatus() failed to set FEC state");
2752 0 : return -1;
2753 : }
2754 0 : return 0;
2755 : }
2756 :
2757 0 : bool Channel::GetCodecFECStatus() {
2758 0 : return codec_manager_.GetStackParams()->use_codec_fec;
2759 : }
2760 :
2761 0 : void Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) {
2762 : // None of these functions can fail.
2763 : // If pacing is enabled we always store packets.
2764 0 : if (!pacing_enabled_)
2765 0 : _rtpRtcpModule->SetStorePacketsStatus(enable, maxNumberOfPackets);
2766 0 : rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets);
2767 0 : if (enable)
2768 0 : audio_coding_->EnableNack(maxNumberOfPackets);
2769 : else
2770 0 : audio_coding_->DisableNack();
2771 0 : }
2772 :
2773 : // Called when we are missing one or more packets.
2774 0 : int Channel::ResendPackets(const uint16_t* sequence_numbers, int length) {
2775 0 : return _rtpRtcpModule->SendNACK(sequence_numbers, length);
2776 : }
2777 :
2778 0 : uint32_t Channel::Demultiplex(const AudioFrame& audioFrame) {
2779 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2780 : "Channel::Demultiplex()");
2781 0 : _audioFrame.CopyFrom(audioFrame);
2782 0 : _audioFrame.id_ = _channelId;
2783 0 : return 0;
2784 : }
2785 :
2786 0 : void Channel::Demultiplex(const int16_t* audio_data,
2787 : int sample_rate,
2788 : size_t number_of_frames,
2789 : size_t number_of_channels) {
2790 : CodecInst codec;
2791 0 : GetSendCodec(codec);
2792 :
2793 : // Never upsample or upmix the capture signal here. This should be done at the
2794 : // end of the send chain.
2795 0 : _audioFrame.sample_rate_hz_ = std::min(codec.plfreq, sample_rate);
2796 0 : _audioFrame.num_channels_ = std::min(number_of_channels, codec.channels);
2797 0 : RemixAndResample(audio_data, number_of_frames, number_of_channels,
2798 0 : sample_rate, &input_resampler_, &_audioFrame);
2799 0 : }
2800 :
2801 0 : uint32_t Channel::PrepareEncodeAndSend(int mixingFrequency) {
2802 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2803 : "Channel::PrepareEncodeAndSend()");
2804 :
2805 0 : if (_audioFrame.samples_per_channel_ == 0) {
2806 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2807 : "Channel::PrepareEncodeAndSend() invalid audio frame");
2808 0 : return 0xFFFFFFFF;
2809 : }
2810 :
2811 0 : if (channel_state_.Get().input_file_playing) {
2812 0 : MixOrReplaceAudioWithFile(mixingFrequency);
2813 : }
2814 :
2815 0 : bool is_muted = InputMute(); // Cache locally as InputMute() takes a lock.
2816 0 : AudioFrameOperations::Mute(&_audioFrame, previous_frame_muted_, is_muted);
2817 :
2818 0 : if (channel_state_.Get().input_external_media) {
2819 0 : rtc::CritScope cs(&_callbackCritSect);
2820 0 : const bool isStereo = (_audioFrame.num_channels_ == 2);
2821 0 : if (_inputExternalMediaCallbackPtr) {
2822 0 : _inputExternalMediaCallbackPtr->Process(
2823 : _channelId, kRecordingPerChannel, (int16_t*)_audioFrame.data_,
2824 : _audioFrame.samples_per_channel_, _audioFrame.sample_rate_hz_,
2825 0 : isStereo);
2826 : }
2827 : }
2828 :
2829 0 : if (_includeAudioLevelIndication) {
2830 : size_t length =
2831 0 : _audioFrame.samples_per_channel_ * _audioFrame.num_channels_;
2832 0 : RTC_CHECK_LE(length, sizeof(_audioFrame.data_));
2833 0 : if (is_muted && previous_frame_muted_) {
2834 0 : rms_level_.AnalyzeMuted(length);
2835 : } else {
2836 0 : rms_level_.Analyze(
2837 0 : rtc::ArrayView<const int16_t>(_audioFrame.data_, length));
2838 : }
2839 : }
2840 0 : previous_frame_muted_ = is_muted;
2841 :
2842 0 : return 0;
2843 : }
2844 :
2845 0 : uint32_t Channel::EncodeAndSend() {
2846 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2847 : "Channel::EncodeAndSend()");
2848 :
2849 0 : assert(_audioFrame.num_channels_ <= 2);
2850 0 : if (_audioFrame.samples_per_channel_ == 0) {
2851 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2852 : "Channel::EncodeAndSend() invalid audio frame");
2853 0 : return 0xFFFFFFFF;
2854 : }
2855 :
2856 0 : _audioFrame.id_ = _channelId;
2857 :
2858 : // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
2859 :
2860 : // The ACM resamples internally.
2861 0 : _audioFrame.timestamp_ = _timeStamp;
2862 : // This call will trigger AudioPacketizationCallback::SendData if encoding
2863 : // is done and payload is ready for packetization and transmission.
2864 : // Otherwise, it will return without invoking the callback.
2865 0 : if (audio_coding_->Add10MsData((AudioFrame&)_audioFrame) < 0) {
2866 : WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
2867 : "Channel::EncodeAndSend() ACM encoding failed");
2868 0 : return 0xFFFFFFFF;
2869 : }
2870 :
2871 0 : _timeStamp += static_cast<uint32_t>(_audioFrame.samples_per_channel_);
2872 0 : return 0;
2873 : }
2874 :
2875 0 : void Channel::set_associate_send_channel(const ChannelOwner& channel) {
2876 0 : RTC_DCHECK(!channel.channel() ||
2877 0 : channel.channel()->ChannelId() != _channelId);
2878 0 : rtc::CritScope lock(&assoc_send_channel_lock_);
2879 0 : associate_send_channel_ = channel;
2880 0 : }
2881 :
2882 0 : void Channel::DisassociateSendChannel(int channel_id) {
2883 0 : rtc::CritScope lock(&assoc_send_channel_lock_);
2884 0 : Channel* channel = associate_send_channel_.channel();
2885 0 : if (channel && channel->ChannelId() == channel_id) {
2886 : // If this channel is associated with a send channel of the specified
2887 : // Channel ID, disassociate with it.
2888 0 : ChannelOwner ref(NULL);
2889 0 : associate_send_channel_ = ref;
2890 : }
2891 0 : }
2892 :
2893 0 : void Channel::SetRtcEventLog(RtcEventLog* event_log) {
2894 0 : event_log_proxy_->SetEventLog(event_log);
2895 0 : }
2896 :
2897 0 : void Channel::SetRtcpRttStats(RtcpRttStats* rtcp_rtt_stats) {
2898 0 : rtcp_rtt_stats_proxy_->SetRtcpRttStats(rtcp_rtt_stats);
2899 0 : }
2900 :
2901 0 : void Channel::UpdateOverheadForEncoder() {
2902 0 : audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
2903 0 : if (*encoder) {
2904 0 : (*encoder)->OnReceivedOverhead(transport_overhead_per_packet_ +
2905 0 : rtp_overhead_per_packet_);
2906 : }
2907 0 : });
2908 0 : }
2909 :
2910 0 : void Channel::SetTransportOverhead(size_t transport_overhead_per_packet) {
2911 0 : transport_overhead_per_packet_ = transport_overhead_per_packet;
2912 0 : UpdateOverheadForEncoder();
2913 0 : }
2914 :
2915 0 : void Channel::OnOverheadChanged(size_t overhead_bytes_per_packet) {
2916 0 : rtp_overhead_per_packet_ = overhead_bytes_per_packet;
2917 0 : UpdateOverheadForEncoder();
2918 0 : }
2919 :
2920 0 : int Channel::RegisterExternalMediaProcessing(ProcessingTypes type,
2921 : VoEMediaProcess& processObject) {
2922 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2923 : "Channel::RegisterExternalMediaProcessing()");
2924 :
2925 0 : rtc::CritScope cs(&_callbackCritSect);
2926 :
2927 0 : if (kPlaybackPerChannel == type) {
2928 0 : if (_outputExternalMediaCallbackPtr) {
2929 0 : _engineStatisticsPtr->SetLastError(
2930 : VE_INVALID_OPERATION, kTraceError,
2931 : "Channel::RegisterExternalMediaProcessing() "
2932 0 : "output external media already enabled");
2933 0 : return -1;
2934 : }
2935 0 : _outputExternalMediaCallbackPtr = &processObject;
2936 0 : _outputExternalMedia = true;
2937 0 : } else if (kRecordingPerChannel == type) {
2938 0 : if (_inputExternalMediaCallbackPtr) {
2939 0 : _engineStatisticsPtr->SetLastError(
2940 : VE_INVALID_OPERATION, kTraceError,
2941 : "Channel::RegisterExternalMediaProcessing() "
2942 0 : "output external media already enabled");
2943 0 : return -1;
2944 : }
2945 0 : _inputExternalMediaCallbackPtr = &processObject;
2946 0 : channel_state_.SetInputExternalMedia(true);
2947 : }
2948 0 : return 0;
2949 : }
2950 :
2951 0 : int Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type) {
2952 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2953 : "Channel::DeRegisterExternalMediaProcessing()");
2954 :
2955 0 : rtc::CritScope cs(&_callbackCritSect);
2956 :
2957 0 : if (kPlaybackPerChannel == type) {
2958 0 : if (!_outputExternalMediaCallbackPtr) {
2959 0 : _engineStatisticsPtr->SetLastError(
2960 : VE_INVALID_OPERATION, kTraceWarning,
2961 : "Channel::DeRegisterExternalMediaProcessing() "
2962 0 : "output external media already disabled");
2963 0 : return 0;
2964 : }
2965 0 : _outputExternalMedia = false;
2966 0 : _outputExternalMediaCallbackPtr = NULL;
2967 0 : } else if (kRecordingPerChannel == type) {
2968 0 : if (!_inputExternalMediaCallbackPtr) {
2969 0 : _engineStatisticsPtr->SetLastError(
2970 : VE_INVALID_OPERATION, kTraceWarning,
2971 : "Channel::DeRegisterExternalMediaProcessing() "
2972 0 : "input external media already disabled");
2973 0 : return 0;
2974 : }
2975 0 : channel_state_.SetInputExternalMedia(false);
2976 0 : _inputExternalMediaCallbackPtr = NULL;
2977 : }
2978 :
2979 0 : return 0;
2980 : }
2981 :
2982 0 : int Channel::SetExternalMixing(bool enabled) {
2983 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2984 : "Channel::SetExternalMixing(enabled=%d)", enabled);
2985 :
2986 0 : if (channel_state_.Get().playing) {
2987 0 : _engineStatisticsPtr->SetLastError(
2988 : VE_INVALID_OPERATION, kTraceError,
2989 : "Channel::SetExternalMixing() "
2990 0 : "external mixing cannot be changed while playing.");
2991 0 : return -1;
2992 : }
2993 :
2994 0 : _externalMixing = enabled;
2995 :
2996 0 : return 0;
2997 : }
2998 :
2999 0 : int Channel::GetNetworkStatistics(NetworkStatistics& stats) {
3000 0 : return audio_coding_->GetNetworkStatistics(&stats);
3001 : }
3002 :
3003 0 : void Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const {
3004 0 : audio_coding_->GetDecodingCallStatistics(stats);
3005 0 : }
3006 :
3007 0 : bool Channel::GetDelayEstimate(int* jitter_buffer_delay_ms,
3008 : int* playout_buffer_delay_ms,
3009 : int* avsync_offset_ms) const {
3010 0 : rtc::CritScope lock(&video_sync_lock_);
3011 0 : *jitter_buffer_delay_ms = audio_coding_->FilteredCurrentDelayMs();
3012 0 : *playout_buffer_delay_ms = playout_delay_ms_;
3013 0 : *avsync_offset_ms = _current_sync_offset;
3014 0 : return true;
3015 : }
3016 :
3017 0 : uint32_t Channel::GetDelayEstimate() const {
3018 0 : int jitter_buffer_delay_ms = 0;
3019 0 : int playout_buffer_delay_ms = 0;
3020 0 : int avsync_offset_ms = 0;
3021 0 : GetDelayEstimate(&jitter_buffer_delay_ms, &playout_buffer_delay_ms, &avsync_offset_ms);
3022 0 : return jitter_buffer_delay_ms + playout_buffer_delay_ms;
3023 : }
3024 :
3025 0 : int Channel::LeastRequiredDelayMs() const {
3026 0 : return audio_coding_->LeastRequiredDelayMs();
3027 : }
3028 :
3029 0 : int Channel::SetMinimumPlayoutDelay(int delayMs) {
3030 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3031 : "Channel::SetMinimumPlayoutDelay()");
3032 0 : if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
3033 : (delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) {
3034 0 : _engineStatisticsPtr->SetLastError(
3035 : VE_INVALID_ARGUMENT, kTraceError,
3036 0 : "SetMinimumPlayoutDelay() invalid min delay");
3037 0 : return -1;
3038 : }
3039 0 : if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) {
3040 0 : _engineStatisticsPtr->SetLastError(
3041 : VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
3042 0 : "SetMinimumPlayoutDelay() failed to set min playout delay");
3043 0 : return -1;
3044 : }
3045 0 : return 0;
3046 : }
3047 :
3048 0 : int Channel::GetPlayoutTimestamp(unsigned int& timestamp) {
3049 0 : uint32_t playout_timestamp_rtp = 0;
3050 : {
3051 0 : rtc::CritScope lock(&video_sync_lock_);
3052 0 : playout_timestamp_rtp = playout_timestamp_rtp_;
3053 : }
3054 0 : if (playout_timestamp_rtp == 0) {
3055 0 : _engineStatisticsPtr->SetLastError(
3056 : VE_CANNOT_RETRIEVE_VALUE, kTraceStateInfo,
3057 0 : "GetPlayoutTimestamp() failed to retrieve timestamp");
3058 0 : return -1;
3059 : }
3060 0 : timestamp = playout_timestamp_rtp;
3061 0 : return 0;
3062 : }
3063 :
3064 0 : int Channel::SetInitTimestamp(unsigned int timestamp) {
3065 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3066 : "Channel::SetInitTimestamp()");
3067 0 : if (channel_state_.Get().sending) {
3068 0 : _engineStatisticsPtr->SetLastError(VE_SENDING, kTraceError,
3069 0 : "SetInitTimestamp() already sending");
3070 0 : return -1;
3071 : }
3072 0 : _rtpRtcpModule->SetStartTimestamp(timestamp);
3073 0 : return 0;
3074 : }
3075 :
3076 0 : int Channel::SetInitSequenceNumber(short sequenceNumber) {
3077 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3078 : "Channel::SetInitSequenceNumber()");
3079 0 : if (channel_state_.Get().sending) {
3080 0 : _engineStatisticsPtr->SetLastError(
3081 0 : VE_SENDING, kTraceError, "SetInitSequenceNumber() already sending");
3082 0 : return -1;
3083 : }
3084 0 : _rtpRtcpModule->SetSequenceNumber(sequenceNumber);
3085 0 : return 0;
3086 : }
3087 :
3088 0 : int Channel::GetRtpRtcp(RtpRtcp** rtpRtcpModule,
3089 : RtpReceiver** rtp_receiver) const {
3090 0 : *rtpRtcpModule = _rtpRtcpModule.get();
3091 0 : *rtp_receiver = rtp_receiver_.get();
3092 0 : return 0;
3093 : }
3094 :
3095 : // TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
3096 : // a shared helper.
3097 0 : int32_t Channel::MixOrReplaceAudioWithFile(int mixingFrequency) {
3098 0 : std::unique_ptr<int16_t[]> fileBuffer(new int16_t[640]);
3099 0 : size_t fileSamples(0);
3100 :
3101 : {
3102 0 : rtc::CritScope cs(&_fileCritSect);
3103 :
3104 0 : if (!input_file_player_) {
3105 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
3106 : "Channel::MixOrReplaceAudioWithFile() fileplayer"
3107 : " doesnt exist");
3108 0 : return -1;
3109 : }
3110 :
3111 0 : if (input_file_player_->Get10msAudioFromFile(fileBuffer.get(), &fileSamples,
3112 0 : mixingFrequency) == -1) {
3113 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
3114 : "Channel::MixOrReplaceAudioWithFile() file mixing "
3115 : "failed");
3116 0 : return -1;
3117 : }
3118 0 : if (fileSamples == 0) {
3119 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
3120 : "Channel::MixOrReplaceAudioWithFile() file is ended");
3121 0 : return 0;
3122 : }
3123 : }
3124 :
3125 0 : assert(_audioFrame.samples_per_channel_ == fileSamples);
3126 :
3127 0 : if (_mixFileWithMicrophone) {
3128 : // Currently file stream is always mono.
3129 : // TODO(xians): Change the code when FilePlayer supports real stereo.
3130 0 : MixWithSat(_audioFrame.data_, _audioFrame.num_channels_, fileBuffer.get(),
3131 0 : 1, fileSamples);
3132 : } else {
3133 : // Replace ACM audio with file.
3134 : // Currently file stream is always mono.
3135 : // TODO(xians): Change the code when FilePlayer supports real stereo.
3136 0 : _audioFrame.UpdateFrame(
3137 0 : _channelId, 0xFFFFFFFF, fileBuffer.get(), fileSamples, mixingFrequency,
3138 0 : AudioFrame::kNormalSpeech, AudioFrame::kVadUnknown, 1);
3139 : }
3140 0 : return 0;
3141 : }
3142 :
3143 0 : int32_t Channel::MixAudioWithFile(AudioFrame& audioFrame, int mixingFrequency) {
3144 0 : assert(mixingFrequency <= 48000);
3145 :
3146 0 : std::unique_ptr<int16_t[]> fileBuffer(new int16_t[960]);
3147 0 : size_t fileSamples(0);
3148 :
3149 : {
3150 0 : rtc::CritScope cs(&_fileCritSect);
3151 :
3152 0 : if (!output_file_player_) {
3153 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
3154 : "Channel::MixAudioWithFile() file mixing failed");
3155 0 : return -1;
3156 : }
3157 :
3158 : // We should get the frequency we ask for.
3159 0 : if (output_file_player_->Get10msAudioFromFile(
3160 0 : fileBuffer.get(), &fileSamples, mixingFrequency) == -1) {
3161 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
3162 : "Channel::MixAudioWithFile() file mixing failed");
3163 0 : return -1;
3164 : }
3165 : }
3166 :
3167 0 : if (audioFrame.samples_per_channel_ == fileSamples) {
3168 : // Currently file stream is always mono.
3169 : // TODO(xians): Change the code when FilePlayer supports real stereo.
3170 0 : MixWithSat(audioFrame.data_, audioFrame.num_channels_, fileBuffer.get(), 1,
3171 0 : fileSamples);
3172 : } else {
3173 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
3174 : "Channel::MixAudioWithFile() samples_per_channel_(%" PRIuS
3175 : ") != "
3176 : "fileSamples(%" PRIuS ")",
3177 : audioFrame.samples_per_channel_, fileSamples);
3178 0 : return -1;
3179 : }
3180 :
3181 0 : return 0;
3182 : }
3183 :
3184 0 : void Channel::UpdatePlayoutTimestamp(bool rtcp) {
3185 0 : jitter_buffer_playout_timestamp_ = audio_coding_->PlayoutTimestamp();
3186 :
3187 0 : if (!jitter_buffer_playout_timestamp_) {
3188 : // This can happen if this channel has not received any RTP packets. In
3189 : // this case, NetEq is not capable of computing a playout timestamp.
3190 0 : return;
3191 : }
3192 :
3193 0 : uint16_t delay_ms = 0;
3194 0 : if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) {
3195 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
3196 : "Channel::UpdatePlayoutTimestamp() failed to read playout"
3197 : " delay from the ADM");
3198 0 : _engineStatisticsPtr->SetLastError(
3199 : VE_CANNOT_RETRIEVE_VALUE, kTraceError,
3200 0 : "UpdatePlayoutTimestamp() failed to retrieve playout delay");
3201 0 : return;
3202 : }
3203 :
3204 0 : RTC_DCHECK(jitter_buffer_playout_timestamp_);
3205 0 : uint32_t playout_timestamp = *jitter_buffer_playout_timestamp_;
3206 :
3207 : // Remove the playout delay.
3208 0 : playout_timestamp -= (delay_ms * (GetRtpTimestampRateHz() / 1000));
3209 :
3210 : WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
3211 : "Channel::UpdatePlayoutTimestamp() => playoutTimestamp = %lu",
3212 : playout_timestamp);
3213 :
3214 : {
3215 0 : rtc::CritScope lock(&video_sync_lock_);
3216 0 : if (rtcp) {
3217 0 : playout_timestamp_rtcp_ = playout_timestamp;
3218 : } else {
3219 0 : playout_timestamp_rtp_ = playout_timestamp;
3220 : }
3221 0 : playout_delay_ms_ = delay_ms;
3222 : }
3223 : }
3224 :
3225 0 : void Channel::RegisterReceiveCodecsToRTPModule() {
3226 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3227 : "Channel::RegisterReceiveCodecsToRTPModule()");
3228 :
3229 : CodecInst codec;
3230 0 : const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
3231 :
3232 0 : for (int idx = 0; idx < nSupportedCodecs; idx++) {
3233 : // Open up the RTP/RTCP receiver for all supported codecs
3234 0 : if ((audio_coding_->Codec(idx, &codec) == -1) ||
3235 0 : (rtp_receiver_->RegisterReceivePayload(codec) == -1)) {
3236 : WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
3237 : "Channel::RegisterReceiveCodecsToRTPModule() unable"
3238 : " to register %s (%d/%d/%" PRIuS
3239 : "/%d) to RTP/RTCP "
3240 : "receiver",
3241 : codec.plname, codec.pltype, codec.plfreq, codec.channels,
3242 : codec.rate);
3243 : } else {
3244 : WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3245 : "Channel::RegisterReceiveCodecsToRTPModule() %s "
3246 : "(%d/%d/%" PRIuS
3247 : "/%d) has been added to the RTP/RTCP "
3248 : "receiver",
3249 : codec.plname, codec.pltype, codec.plfreq, codec.channels,
3250 : codec.rate);
3251 : }
3252 : }
3253 0 : }
3254 :
3255 0 : int Channel::SetSendRtpHeaderExtension(bool enable,
3256 : RTPExtensionType type,
3257 : unsigned char id) {
3258 0 : int error = 0;
3259 0 : _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type);
3260 0 : if (enable) {
3261 0 : error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(type, id);
3262 : }
3263 0 : return error;
3264 : }
3265 :
3266 0 : int Channel::GetRtpTimestampRateHz() const {
3267 0 : const auto format = audio_coding_->ReceiveFormat();
3268 : // Default to the playout frequency if we've not gotten any packets yet.
3269 : // TODO(ossu): Zero clockrate can only happen if we've added an external
3270 : // decoder for a format we don't support internally. Remove once that way of
3271 : // adding decoders is gone!
3272 0 : return (format && format->clockrate_hz != 0)
3273 0 : ? format->clockrate_hz
3274 0 : : audio_coding_->PlayoutFrequency();
3275 : }
3276 :
3277 0 : int64_t Channel::GetRTT(bool allow_associate_channel) const {
3278 0 : RtcpMode method = _rtpRtcpModule->RTCP();
3279 0 : if (method == RtcpMode::kOff) {
3280 0 : return 0;
3281 : }
3282 0 : std::vector<RTCPReportBlock> report_blocks;
3283 0 : _rtpRtcpModule->RemoteRTCPStat(&report_blocks);
3284 :
3285 0 : int64_t rtt = 0;
3286 0 : if (report_blocks.empty()) {
3287 0 : if (allow_associate_channel) {
3288 0 : rtc::CritScope lock(&assoc_send_channel_lock_);
3289 0 : Channel* channel = associate_send_channel_.channel();
3290 : // Tries to get RTT from an associated channel. This is important for
3291 : // receive-only channels.
3292 0 : if (channel) {
3293 : // To prevent infinite recursion and deadlock, calling GetRTT of
3294 : // associate channel should always use "false" for argument:
3295 : // |allow_associate_channel|.
3296 0 : rtt = channel->GetRTT(false);
3297 : }
3298 : }
3299 0 : return rtt;
3300 : }
3301 :
3302 0 : uint32_t remoteSSRC = rtp_receiver_->SSRC();
3303 0 : std::vector<RTCPReportBlock>::const_iterator it = report_blocks.begin();
3304 0 : for (; it != report_blocks.end(); ++it) {
3305 0 : if (it->remoteSSRC == remoteSSRC)
3306 0 : break;
3307 : }
3308 0 : if (it == report_blocks.end()) {
3309 : // We have not received packets with SSRC matching the report blocks.
3310 : // To calculate RTT we try with the SSRC of the first report block.
3311 : // This is very important for send-only channels where we don't know
3312 : // the SSRC of the other end.
3313 0 : remoteSSRC = report_blocks[0].remoteSSRC;
3314 : }
3315 :
3316 0 : int64_t avg_rtt = 0;
3317 0 : int64_t max_rtt = 0;
3318 0 : int64_t min_rtt = 0;
3319 0 : if (_rtpRtcpModule->RTT(remoteSSRC, &rtt, &avg_rtt, &min_rtt, &max_rtt) !=
3320 : 0) {
3321 0 : return 0;
3322 : }
3323 0 : return rtt;
3324 : }
3325 :
3326 : } // namespace voe
3327 : } // namespace webrtc
|