| /* |
| * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #ifndef AUDIO_VOIP_AUDIO_EGRESS_H_ |
| #define AUDIO_VOIP_AUDIO_EGRESS_H_ |
| |
| #include <memory> |
| #include <string> |
| |
| #include "api/audio_codecs/audio_format.h" |
| #include "api/task_queue/task_queue_factory.h" |
| #include "audio/audio_level.h" |
| #include "audio/utility/audio_frame_operations.h" |
| #include "call/audio_sender.h" |
| #include "modules/audio_coding/include/audio_coding_module.h" |
| #include "modules/rtp_rtcp/include/report_block_data.h" |
| #include "modules/rtp_rtcp/source/rtp_rtcp_interface.h" |
| #include "modules/rtp_rtcp/source/rtp_sender_audio.h" |
| #include "rtc_base/synchronization/mutex.h" |
| #include "rtc_base/task_queue.h" |
| #include "rtc_base/thread_checker.h" |
| #include "rtc_base/time_utils.h" |
| |
| namespace webrtc { |
| |
| // AudioEgress receives input samples from AudioDeviceModule via |
| // AudioTransportImpl through AudioSender interface. Once it encodes the sample |
| // via selected encoder through AudioPacketizationCallback interface, the |
| // encoded payload will be packetized by the RTP stack, resulting in ready to |
| // send RTP packet to remote endpoint. |
| // |
| // TaskQueue is used to encode and send RTP asynchrounously as some OS platform |
| // uses the same thread for both audio input and output sample deliveries which |
| // can affect audio quality. |
| // |
| // Note that this class is originally based on ChannelSend in |
| // audio/channel_send.cc with non-audio related logic trimmed as aimed for |
| // smaller footprint. |
| class AudioEgress : public AudioSender, public AudioPacketizationCallback { |
| public: |
| AudioEgress(RtpRtcpInterface* rtp_rtcp, |
| Clock* clock, |
| TaskQueueFactory* task_queue_factory); |
| ~AudioEgress() override; |
| |
| // Set the encoder format and payload type for AudioCodingModule. |
| // It's possible to change the encoder type during its active usage. |
| // |payload_type| must be the type that is negotiated with peer through |
| // offer/answer. |
| void SetEncoder(int payload_type, |
| const SdpAudioFormat& encoder_format, |
| std::unique_ptr<AudioEncoder> encoder); |
| |
| // Start or stop sending operation of AudioEgress. This will start/stop |
| // the RTP stack also causes encoder queue thread to start/stop |
| // processing input audio samples. StartSend will return false if |
| // a send codec has not been set. |
| bool StartSend(); |
| void StopSend(); |
| |
| // Query the state of the RTP stack. This returns true if StartSend() |
| // called and false if StopSend() is called. |
| bool IsSending() const; |
| |
| // Enable or disable Mute state. |
| void SetMute(bool mute); |
| |
| // Retrieve current encoder format info. This returns encoder format set |
| // by SetEncoder() and if encoder is not set, this will return nullopt. |
| absl::optional<SdpAudioFormat> GetEncoderFormat() const { |
| MutexLock lock(&lock_); |
| return encoder_format_; |
| } |
| |
| // Register the payload type and sample rate for DTMF (RFC 4733) payload. |
| void RegisterTelephoneEventType(int rtp_payload_type, int sample_rate_hz); |
| |
| // Send DTMF named event as specified by |
| // https://tools.ietf.org/html/rfc4733#section-3.2 |
| // |duration_ms| specifies the duration of DTMF packets that will be emitted |
| // in place of real RTP packets instead. |
| // This will return true when requested dtmf event is successfully scheduled |
| // otherwise false when the dtmf queue reached maximum of 20 events. |
| bool SendTelephoneEvent(int dtmf_event, int duration_ms); |
| |
| // See comments on LevelFullRange, TotalEnergy, TotalDuration from |
| // audio/audio_level.h. |
| int GetInputAudioLevel() const { return input_audio_level_.LevelFullRange(); } |
| double GetInputTotalEnergy() const { |
| return input_audio_level_.TotalEnergy(); |
| } |
| double GetInputTotalDuration() const { |
| return input_audio_level_.TotalDuration(); |
| } |
| |
| // Implementation of AudioSender interface. |
| void SendAudioData(std::unique_ptr<AudioFrame> audio_frame) override; |
| |
| // Implementation of AudioPacketizationCallback interface. |
| int32_t SendData(AudioFrameType frame_type, |
| uint8_t payload_type, |
| uint32_t timestamp, |
| const uint8_t* payload_data, |
| size_t payload_size) override; |
| |
| private: |
| void SetEncoderFormat(const SdpAudioFormat& encoder_format) { |
| MutexLock lock(&lock_); |
| encoder_format_ = encoder_format; |
| } |
| |
| mutable Mutex lock_; |
| |
| // Current encoder format selected by caller. |
| absl::optional<SdpAudioFormat> encoder_format_ RTC_GUARDED_BY(lock_); |
| |
| // Synchronization is handled internally by RtpRtcp. |
| RtpRtcpInterface* const rtp_rtcp_; |
| |
| // Synchronization is handled internally by RTPSenderAudio. |
| RTPSenderAudio rtp_sender_audio_; |
| |
| // Synchronization is handled internally by AudioCodingModule. |
| const std::unique_ptr<AudioCodingModule> audio_coding_; |
| |
| // Synchronization is handled internally by voe::AudioLevel. |
| voe::AudioLevel input_audio_level_; |
| |
| // Struct that holds all variables used by encoder task queue. |
| struct EncoderContext { |
| // Offset used to mark rtp timestamp in sample rate unit in |
| // newly received audio frame from AudioTransport. |
| uint32_t frame_rtp_timestamp_ = 0; |
| |
| // Flag to track mute state from caller. |previously_muted_| is used to |
| // track previous state as part of input to AudioFrameOperations::Mute |
| // to implement fading effect when (un)mute is invoked. |
| bool mute_ = false; |
| bool previously_muted_ = false; |
| }; |
| |
| EncoderContext encoder_context_ RTC_GUARDED_BY(encoder_queue_); |
| |
| // Defined last to ensure that there are no running tasks when the other |
| // members are destroyed. |
| rtc::TaskQueue encoder_queue_; |
| }; |
| |
| } // namespace webrtc |
| |
| #endif // AUDIO_VOIP_AUDIO_EGRESS_H_ |