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 void AudioEgress::StartSend() {
60 rtp_rtcp_->SetSendingMediaStatus(true);
61 }
62
StopSend()63 void AudioEgress::StopSend() {
64 rtp_rtcp_->SetSendingMediaStatus(false);
65 }
66
SendAudioData(std::unique_ptr<AudioFrame> audio_frame)67 void AudioEgress::SendAudioData(std::unique_ptr<AudioFrame> audio_frame) {
68 RTC_DCHECK_GT(audio_frame->samples_per_channel_, 0);
69 RTC_DCHECK_LE(audio_frame->num_channels_, 8);
70
71 encoder_queue_.PostTask(
72 [this, audio_frame = std::move(audio_frame)]() mutable {
73 RTC_DCHECK_RUN_ON(&encoder_queue_);
74 if (!rtp_rtcp_->SendingMedia()) {
75 return;
76 }
77
78 AudioFrameOperations::Mute(audio_frame.get(),
79 encoder_context_.previously_muted_,
80 encoder_context_.mute_);
81 encoder_context_.previously_muted_ = encoder_context_.mute_;
82
83 audio_frame->timestamp_ = encoder_context_.frame_rtp_timestamp_;
84
85 // This call will trigger AudioPacketizationCallback::SendData if
86 // encoding is done and payload is ready for packetization and
87 // transmission. Otherwise, it will return without invoking the
88 // callback.
89 if (audio_coding_->Add10MsData(*audio_frame) < 0) {
90 RTC_DLOG(LS_ERROR) << "ACM::Add10MsData() failed.";
91 return;
92 }
93
94 encoder_context_.frame_rtp_timestamp_ +=
95 rtc::dchecked_cast<uint32_t>(audio_frame->samples_per_channel_);
96 });
97 }
98
SendData(AudioFrameType frame_type,uint8_t payload_type,uint32_t timestamp,const uint8_t * payload_data,size_t payload_size)99 int32_t AudioEgress::SendData(AudioFrameType frame_type,
100 uint8_t payload_type,
101 uint32_t timestamp,
102 const uint8_t* payload_data,
103 size_t payload_size) {
104 RTC_DCHECK_RUN_ON(&encoder_queue_);
105
106 rtc::ArrayView<const uint8_t> payload(payload_data, payload_size);
107
108 // Currently we don't get a capture time from downstream modules (ADM,
109 // AudioTransportImpl).
110 // TODO(natim@webrtc.org): Integrate once it's ready.
111 constexpr uint32_t kUndefinedCaptureTime = -1;
112
113 // Push data from ACM to RTP/RTCP-module to deliver audio frame for
114 // packetization.
115 if (!rtp_rtcp_->OnSendingRtpFrame(timestamp, kUndefinedCaptureTime,
116 payload_type,
117 /*force_sender_report=*/false)) {
118 return -1;
119 }
120
121 const uint32_t rtp_timestamp = timestamp + rtp_rtcp_->StartTimestamp();
122
123 // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
124 if (!rtp_sender_audio_.SendAudio(frame_type, payload_type, rtp_timestamp,
125 payload.data(), payload.size())) {
126 RTC_DLOG(LS_ERROR)
127 << "AudioEgress::SendData() failed to send data to RTP/RTCP module";
128 return -1;
129 }
130
131 return 0;
132 }
133
RegisterTelephoneEventType(int rtp_payload_type,int sample_rate_hz)134 void AudioEgress::RegisterTelephoneEventType(int rtp_payload_type,
135 int sample_rate_hz) {
136 RTC_DCHECK_GE(rtp_payload_type, 0);
137 RTC_DCHECK_LE(rtp_payload_type, 127);
138
139 rtp_rtcp_->RegisterSendPayloadFrequency(rtp_payload_type, sample_rate_hz);
140 rtp_sender_audio_.RegisterAudioPayload("telephone-event", rtp_payload_type,
141 sample_rate_hz, 0, 0);
142 }
143
SendTelephoneEvent(int dtmf_event,int duration_ms)144 bool AudioEgress::SendTelephoneEvent(int dtmf_event, int duration_ms) {
145 RTC_DCHECK_GE(dtmf_event, 0);
146 RTC_DCHECK_LE(dtmf_event, 255);
147 RTC_DCHECK_GE(duration_ms, 0);
148 RTC_DCHECK_LE(duration_ms, 65535);
149
150 if (!IsSending()) {
151 return false;
152 }
153
154 constexpr int kTelephoneEventAttenuationdB = 10;
155
156 if (rtp_sender_audio_.SendTelephoneEvent(dtmf_event, duration_ms,
157 kTelephoneEventAttenuationdB) != 0) {
158 RTC_DLOG(LS_ERROR) << "SendTelephoneEvent() failed to send event";
159 return false;
160 }
161 return true;
162 }
163
SetMute(bool mute)164 void AudioEgress::SetMute(bool mute) {
165 encoder_queue_.PostTask([this, mute] {
166 RTC_DCHECK_RUN_ON(&encoder_queue_);
167 encoder_context_.mute_ = mute;
168 });
169 }
170
171 } // namespace webrtc
172