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 #ifndef AUDIO_VOIP_AUDIO_EGRESS_H_ 12 #define AUDIO_VOIP_AUDIO_EGRESS_H_ 13 14 #include <memory> 15 #include <string> 16 17 #include "api/audio_codecs/audio_format.h" 18 #include "api/sequence_checker.h" 19 #include "api/task_queue/task_queue_factory.h" 20 #include "audio/audio_level.h" 21 #include "audio/utility/audio_frame_operations.h" 22 #include "call/audio_sender.h" 23 #include "modules/audio_coding/include/audio_coding_module.h" 24 #include "modules/rtp_rtcp/include/report_block_data.h" 25 #include "modules/rtp_rtcp/source/rtp_rtcp_interface.h" 26 #include "modules/rtp_rtcp/source/rtp_sender_audio.h" 27 #include "rtc_base/synchronization/mutex.h" 28 #include "rtc_base/task_queue.h" 29 #include "rtc_base/time_utils.h" 30 31 namespace webrtc { 32 33 // AudioEgress receives input samples from AudioDeviceModule via 34 // AudioTransportImpl through AudioSender interface. Once it encodes the sample 35 // via selected encoder through AudioPacketizationCallback interface, the 36 // encoded payload will be packetized by the RTP stack, resulting in ready to 37 // send RTP packet to remote endpoint. 38 // 39 // TaskQueue is used to encode and send RTP asynchrounously as some OS platform 40 // uses the same thread for both audio input and output sample deliveries which 41 // can affect audio quality. 42 // 43 // Note that this class is originally based on ChannelSend in 44 // audio/channel_send.cc with non-audio related logic trimmed as aimed for 45 // smaller footprint. 46 class AudioEgress : public AudioSender, public AudioPacketizationCallback { 47 public: 48 AudioEgress(RtpRtcpInterface* rtp_rtcp, 49 Clock* clock, 50 TaskQueueFactory* task_queue_factory); 51 ~AudioEgress() override; 52 53 // Set the encoder format and payload type for AudioCodingModule. 54 // It's possible to change the encoder type during its active usage. 55 // `payload_type` must be the type that is negotiated with peer through 56 // offer/answer. 57 void SetEncoder(int payload_type, 58 const SdpAudioFormat& encoder_format, 59 std::unique_ptr<AudioEncoder> encoder); 60 61 // Start or stop sending operation of AudioEgress. This will start/stop 62 // the RTP stack also causes encoder queue thread to start/stop 63 // processing input audio samples. StartSend will return false if 64 // a send codec has not been set. 65 bool StartSend(); 66 void StopSend(); 67 68 // Query the state of the RTP stack. This returns true if StartSend() 69 // called and false if StopSend() is called. 70 bool IsSending() const; 71 72 // Enable or disable Mute state. 73 void SetMute(bool mute); 74 75 // Retrieve current encoder format info. This returns encoder format set 76 // by SetEncoder() and if encoder is not set, this will return nullopt. GetEncoderFormat()77 absl::optional<SdpAudioFormat> GetEncoderFormat() const { 78 MutexLock lock(&lock_); 79 return encoder_format_; 80 } 81 82 // Register the payload type and sample rate for DTMF (RFC 4733) payload. 83 void RegisterTelephoneEventType(int rtp_payload_type, int sample_rate_hz); 84 85 // Send DTMF named event as specified by 86 // https://tools.ietf.org/html/rfc4733#section-3.2 87 // `duration_ms` specifies the duration of DTMF packets that will be emitted 88 // in place of real RTP packets instead. 89 // This will return true when requested dtmf event is successfully scheduled 90 // otherwise false when the dtmf queue reached maximum of 20 events. 91 bool SendTelephoneEvent(int dtmf_event, int duration_ms); 92 93 // See comments on LevelFullRange, TotalEnergy, TotalDuration from 94 // audio/audio_level.h. GetInputAudioLevel()95 int GetInputAudioLevel() const { return input_audio_level_.LevelFullRange(); } GetInputTotalEnergy()96 double GetInputTotalEnergy() const { 97 return input_audio_level_.TotalEnergy(); 98 } GetInputTotalDuration()99 double GetInputTotalDuration() const { 100 return input_audio_level_.TotalDuration(); 101 } 102 103 // Implementation of AudioSender interface. 104 void SendAudioData(std::unique_ptr<AudioFrame> audio_frame) override; 105 106 // Implementation of AudioPacketizationCallback interface. 107 int32_t SendData(AudioFrameType frame_type, 108 uint8_t payload_type, 109 uint32_t timestamp, 110 const uint8_t* payload_data, 111 size_t payload_size) override; 112 113 private: SetEncoderFormat(const SdpAudioFormat & encoder_format)114 void SetEncoderFormat(const SdpAudioFormat& encoder_format) { 115 MutexLock lock(&lock_); 116 encoder_format_ = encoder_format; 117 } 118 119 mutable Mutex lock_; 120 121 // Current encoder format selected by caller. 122 absl::optional<SdpAudioFormat> encoder_format_ RTC_GUARDED_BY(lock_); 123 124 // Synchronization is handled internally by RtpRtcp. 125 RtpRtcpInterface* const rtp_rtcp_; 126 127 // Synchronization is handled internally by RTPSenderAudio. 128 RTPSenderAudio rtp_sender_audio_; 129 130 // Synchronization is handled internally by AudioCodingModule. 131 const std::unique_ptr<AudioCodingModule> audio_coding_; 132 133 // Synchronization is handled internally by voe::AudioLevel. 134 voe::AudioLevel input_audio_level_; 135 136 // Struct that holds all variables used by encoder task queue. 137 struct EncoderContext { 138 // Offset used to mark rtp timestamp in sample rate unit in 139 // newly received audio frame from AudioTransport. 140 uint32_t frame_rtp_timestamp_ = 0; 141 142 // Flag to track mute state from caller. `previously_muted_` is used to 143 // track previous state as part of input to AudioFrameOperations::Mute 144 // to implement fading effect when (un)mute is invoked. 145 bool mute_ = false; 146 bool previously_muted_ = false; 147 }; 148 149 EncoderContext encoder_context_ RTC_GUARDED_BY(encoder_queue_); 150 151 // Defined last to ensure that there are no running tasks when the other 152 // members are destroyed. 153 rtc::TaskQueue encoder_queue_; 154 }; 155 156 } // namespace webrtc 157 158 #endif // AUDIO_VOIP_AUDIO_EGRESS_H_ 159