159 lines
5.9 KiB
C++
159 lines
5.9 KiB
C++
/*
|
|
* 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_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/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_
|