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_egress.h"
12
13 #include <utility>
14 #include <vector>
15
16 #include "rtc_base/logging.h"
17
18 namespace webrtc {
19
AudioEgress(RtpRtcpInterface * rtp_rtcp,Clock * clock,TaskQueueFactory * task_queue_factory)20 AudioEgress::AudioEgress(RtpRtcpInterface* rtp_rtcp,
21 Clock* clock,
22 TaskQueueFactory* task_queue_factory)
23 : rtp_rtcp_(rtp_rtcp),
24 rtp_sender_audio_(clock, rtp_rtcp_->RtpSender()),
25 audio_coding_(AudioCodingModule::Create(AudioCodingModule::Config())),
26 encoder_queue_(task_queue_factory->CreateTaskQueue(
27 "AudioEncoder",
28 TaskQueueFactory::Priority::NORMAL)) {
29 audio_coding_->RegisterTransportCallback(this);
30 }
31
~AudioEgress()32 AudioEgress::~AudioEgress() {
33 audio_coding_->RegisterTransportCallback(nullptr);
34 }
35
IsSending() const36 bool AudioEgress::IsSending() const {
37 return rtp_rtcp_->SendingMedia();
38 }
39
SetEncoder(int payload_type,const SdpAudioFormat & encoder_format,std::unique_ptr<AudioEncoder> encoder)40 void AudioEgress::SetEncoder(int payload_type,
41 const SdpAudioFormat& encoder_format,
42 std::unique_ptr<AudioEncoder> encoder) {
43 RTC_DCHECK_GE(payload_type, 0);
44 RTC_DCHECK_LE(payload_type, 127);
45
46 SetEncoderFormat(encoder_format);
47
48 // The RTP/RTCP module needs to know the RTP timestamp rate (i.e. clockrate)
49 // as well as some other things, so we collect this info and send it along.
50 rtp_rtcp_->RegisterSendPayloadFrequency(payload_type,
51 encoder->RtpTimestampRateHz());
52 rtp_sender_audio_.RegisterAudioPayload("audio", payload_type,
53 encoder->RtpTimestampRateHz(),
54 encoder->NumChannels(), 0);
55
56 audio_coding_->SetEncoder(std::move(encoder));
57 }
58
StartSend()59 bool AudioEgress::StartSend() {
60 if (!GetEncoderFormat()) {
61 RTC_DLOG(LS_WARNING) << "Send codec has not been set yet";
62 return false;
63 }
64 rtp_rtcp_->SetSendingMediaStatus(true);
65 return true;
66 }
67
StopSend()68 void AudioEgress::StopSend() {
69 rtp_rtcp_->SetSendingMediaStatus(false);
70 }
71
SendAudioData(std::unique_ptr<AudioFrame> audio_frame)72 void AudioEgress::SendAudioData(std::unique_ptr<AudioFrame> audio_frame) {
73 RTC_DCHECK_GT(audio_frame->samples_per_channel_, 0);
74 RTC_DCHECK_LE(audio_frame->num_channels_, 8);
75
76 encoder_queue_.PostTask(
77 [this, audio_frame = std::move(audio_frame)]() mutable {
78 RTC_DCHECK_RUN_ON(&encoder_queue_);
79 if (!rtp_rtcp_->SendingMedia()) {
80 return;
81 }
82
83 double duration_seconds =
84 static_cast<double>(audio_frame->samples_per_channel_) /
85 audio_frame->sample_rate_hz_;
86
87 input_audio_level_.ComputeLevel(*audio_frame, duration_seconds);
88
89 AudioFrameOperations::Mute(audio_frame.get(),
90 encoder_context_.previously_muted_,
91 encoder_context_.mute_);
92 encoder_context_.previously_muted_ = encoder_context_.mute_;
93
94 audio_frame->timestamp_ = encoder_context_.frame_rtp_timestamp_;
95
96 // This call will trigger AudioPacketizationCallback::SendData if
97 // encoding is done and payload is ready for packetization and
98 // transmission. Otherwise, it will return without invoking the
99 // callback.
100 if (audio_coding_->Add10MsData(*audio_frame) < 0) {
101 RTC_DLOG(LS_ERROR) << "ACM::Add10MsData() failed.";
102 return;
103 }
104
105 encoder_context_.frame_rtp_timestamp_ +=
106 rtc::dchecked_cast<uint32_t>(audio_frame->samples_per_channel_);
107 });
108 }
109
SendData(AudioFrameType frame_type,uint8_t payload_type,uint32_t timestamp,const uint8_t * payload_data,size_t payload_size)110 int32_t AudioEgress::SendData(AudioFrameType frame_type,
111 uint8_t payload_type,
112 uint32_t timestamp,
113 const uint8_t* payload_data,
114 size_t payload_size) {
115 RTC_DCHECK_RUN_ON(&encoder_queue_);
116
117 rtc::ArrayView<const uint8_t> payload(payload_data, payload_size);
118
119 // Currently we don't get a capture time from downstream modules (ADM,
120 // AudioTransportImpl).
121 // TODO(natim@webrtc.org): Integrate once it's ready.
122 constexpr uint32_t kUndefinedCaptureTime = -1;
123
124 // Push data from ACM to RTP/RTCP-module to deliver audio frame for
125 // packetization.
126 if (!rtp_rtcp_->OnSendingRtpFrame(timestamp, kUndefinedCaptureTime,
127 payload_type,
128 /*force_sender_report=*/false)) {
129 return -1;
130 }
131
132 const uint32_t rtp_timestamp = timestamp + rtp_rtcp_->StartTimestamp();
133
134 // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
135 if (!rtp_sender_audio_.SendAudio(frame_type, payload_type, rtp_timestamp,
136 payload.data(), payload.size())) {
137 RTC_DLOG(LS_ERROR)
138 << "AudioEgress::SendData() failed to send data to RTP/RTCP module";
139 return -1;
140 }
141
142 return 0;
143 }
144
RegisterTelephoneEventType(int rtp_payload_type,int sample_rate_hz)145 void AudioEgress::RegisterTelephoneEventType(int rtp_payload_type,
146 int sample_rate_hz) {
147 RTC_DCHECK_GE(rtp_payload_type, 0);
148 RTC_DCHECK_LE(rtp_payload_type, 127);
149
150 rtp_rtcp_->RegisterSendPayloadFrequency(rtp_payload_type, sample_rate_hz);
151 rtp_sender_audio_.RegisterAudioPayload("telephone-event", rtp_payload_type,
152 sample_rate_hz, 0, 0);
153 }
154
SendTelephoneEvent(int dtmf_event,int duration_ms)155 bool AudioEgress::SendTelephoneEvent(int dtmf_event, int duration_ms) {
156 RTC_DCHECK_GE(dtmf_event, 0);
157 RTC_DCHECK_LE(dtmf_event, 255);
158 RTC_DCHECK_GE(duration_ms, 0);
159 RTC_DCHECK_LE(duration_ms, 65535);
160
161 if (!IsSending()) {
162 return false;
163 }
164
165 constexpr int kTelephoneEventAttenuationdB = 10;
166
167 if (rtp_sender_audio_.SendTelephoneEvent(dtmf_event, duration_ms,
168 kTelephoneEventAttenuationdB) != 0) {
169 RTC_DLOG(LS_ERROR) << "SendTelephoneEvent() failed to send event";
170 return false;
171 }
172 return true;
173 }
174
SetMute(bool mute)175 void AudioEgress::SetMute(bool mute) {
176 encoder_queue_.PostTask([this, mute] {
177 RTC_DCHECK_RUN_ON(&encoder_queue_);
178 encoder_context_.mute_ = mute;
179 });
180 }
181
182 } // namespace webrtc
183