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