1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
/*
* 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/sequence_checker.h"
#include "api/task_queue/task_queue_base.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/system/no_unique_address.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_checker_);
std::unique_ptr<TaskQueueBase, TaskQueueDeleter> encoder_queue_;
RTC_NO_UNIQUE_ADDRESS SequenceChecker encoder_queue_checker_;
};
} // namespace webrtc
#endif // AUDIO_VOIP_AUDIO_EGRESS_H_
|