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