1 /*
2 * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "audio/voip/audio_channel.h"
12
13 #include <utility>
14 #include <vector>
15
16 #include "api/audio_codecs/audio_format.h"
17 #include "api/task_queue/task_queue_factory.h"
18 #include "modules/rtp_rtcp/include/receive_statistics.h"
19 #include "modules/rtp_rtcp/source/rtp_rtcp_impl2.h"
20 #include "rtc_base/location.h"
21 #include "rtc_base/logging.h"
22
23 namespace webrtc {
24
25 namespace {
26
27 constexpr int kRtcpReportIntervalMs = 5000;
28
29 } // namespace
30
AudioChannel(Transport * transport,uint32_t local_ssrc,TaskQueueFactory * task_queue_factory,ProcessThread * process_thread,AudioMixer * audio_mixer,rtc::scoped_refptr<AudioDecoderFactory> decoder_factory)31 AudioChannel::AudioChannel(
32 Transport* transport,
33 uint32_t local_ssrc,
34 TaskQueueFactory* task_queue_factory,
35 ProcessThread* process_thread,
36 AudioMixer* audio_mixer,
37 rtc::scoped_refptr<AudioDecoderFactory> decoder_factory)
38 : audio_mixer_(audio_mixer), process_thread_(process_thread) {
39 RTC_DCHECK(task_queue_factory);
40 RTC_DCHECK(process_thread);
41 RTC_DCHECK(audio_mixer);
42
43 Clock* clock = Clock::GetRealTimeClock();
44 receive_statistics_ = ReceiveStatistics::Create(clock);
45
46 RtpRtcpInterface::Configuration rtp_config;
47 rtp_config.clock = clock;
48 rtp_config.audio = true;
49 rtp_config.receive_statistics = receive_statistics_.get();
50 rtp_config.rtcp_report_interval_ms = kRtcpReportIntervalMs;
51 rtp_config.outgoing_transport = transport;
52 rtp_config.local_media_ssrc = local_ssrc;
53
54 rtp_rtcp_ = ModuleRtpRtcpImpl2::Create(rtp_config);
55
56 rtp_rtcp_->SetSendingMediaStatus(false);
57 rtp_rtcp_->SetRTCPStatus(RtcpMode::kCompound);
58
59 // ProcessThread periodically services RTP stack for RTCP.
60 process_thread_->RegisterModule(rtp_rtcp_.get(), RTC_FROM_HERE);
61
62 ingress_ = std::make_unique<AudioIngress>(rtp_rtcp_.get(), clock,
63 receive_statistics_.get(),
64 std::move(decoder_factory));
65 egress_ =
66 std::make_unique<AudioEgress>(rtp_rtcp_.get(), clock, task_queue_factory);
67
68 // Set the instance of audio ingress to be part of audio mixer for ADM to
69 // fetch audio samples to play.
70 audio_mixer_->AddSource(ingress_.get());
71 }
72
~AudioChannel()73 AudioChannel::~AudioChannel() {
74 if (egress_->IsSending()) {
75 StopSend();
76 }
77 if (ingress_->IsPlaying()) {
78 StopPlay();
79 }
80
81 audio_mixer_->RemoveSource(ingress_.get());
82 process_thread_->DeRegisterModule(rtp_rtcp_.get());
83 }
84
StartSend()85 void AudioChannel::StartSend() {
86 egress_->StartSend();
87
88 // Start sending with RTP stack if it has not been sending yet.
89 if (!rtp_rtcp_->Sending() && rtp_rtcp_->SetSendingStatus(true) != 0) {
90 RTC_DLOG(LS_ERROR) << "StartSend() RTP/RTCP failed to start sending";
91 }
92 }
93
StopSend()94 void AudioChannel::StopSend() {
95 egress_->StopSend();
96
97 // If the channel is not playing and RTP stack is active then deactivate RTP
98 // stack. SetSendingStatus(false) triggers the transmission of RTCP BYE
99 // message to remote endpoint.
100 if (!IsPlaying() && rtp_rtcp_->Sending() &&
101 rtp_rtcp_->SetSendingStatus(false) != 0) {
102 RTC_DLOG(LS_ERROR) << "StopSend() RTP/RTCP failed to stop sending";
103 }
104 }
105
StartPlay()106 void AudioChannel::StartPlay() {
107 ingress_->StartPlay();
108
109 // If RTP stack is not sending then start sending as in recv-only mode, RTCP
110 // receiver report is expected.
111 if (!rtp_rtcp_->Sending() && rtp_rtcp_->SetSendingStatus(true) != 0) {
112 RTC_DLOG(LS_ERROR) << "StartPlay() RTP/RTCP failed to start sending";
113 }
114 }
115
StopPlay()116 void AudioChannel::StopPlay() {
117 ingress_->StopPlay();
118
119 // Deactivate RTP stack only when both sending and receiving are stopped.
120 if (!IsSendingMedia() && rtp_rtcp_->Sending() &&
121 rtp_rtcp_->SetSendingStatus(false) != 0) {
122 RTC_DLOG(LS_ERROR) << "StopPlay() RTP/RTCP failed to stop sending";
123 }
124 }
125
126 } // namespace webrtc
127