• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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