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