Niels Möller | 530ead4 | 2018-10-04 14:28:39 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2012 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_CHANNEL_SEND_H_ |
| 12 | #define AUDIO_CHANNEL_SEND_H_ |
| 13 | |
| 14 | #include <map> |
| 15 | #include <memory> |
| 16 | #include <string> |
| 17 | #include <vector> |
| 18 | |
| 19 | #include "api/audio/audio_frame.h" |
| 20 | #include "api/audio_codecs/audio_encoder.h" |
| 21 | #include "api/call/transport.h" |
Benjamin Wright | bfb444c | 2018-10-15 10:20:24 -0700 | [diff] [blame] | 22 | #include "api/crypto/cryptooptions.h" |
Niels Möller | 7d76a31 | 2018-10-26 12:57:07 +0200 | [diff] [blame] | 23 | #include "api/media_transport_interface.h" |
Niels Möller | 530ead4 | 2018-10-04 14:28:39 +0200 | [diff] [blame] | 24 | #include "common_types.h" // NOLINT(build/include) |
| 25 | #include "modules/audio_coding/include/audio_coding_module.h" |
| 26 | #include "modules/audio_processing/rms_level.h" |
| 27 | #include "modules/rtp_rtcp/include/rtp_rtcp.h" |
| 28 | #include "rtc_base/criticalsection.h" |
| 29 | #include "rtc_base/task_queue.h" |
| 30 | #include "rtc_base/thread_checker.h" |
| 31 | |
| 32 | // TODO(solenberg, nisse): This file contains a few NOLINT marks, to silence |
| 33 | // warnings about use of unsigned short, and non-const reference arguments. |
| 34 | // These need cleanup, in a separate cl. |
| 35 | |
| 36 | namespace rtc { |
| 37 | class TimestampWrapAroundHandler; |
| 38 | } |
| 39 | |
| 40 | namespace webrtc { |
| 41 | |
Benjamin Wright | 84583f6 | 2018-10-04 14:22:34 -0700 | [diff] [blame] | 42 | class FrameEncryptorInterface; |
Niels Möller | 530ead4 | 2018-10-04 14:28:39 +0200 | [diff] [blame] | 43 | class PacketRouter; |
| 44 | class ProcessThread; |
| 45 | class RateLimiter; |
| 46 | class RtcEventLog; |
| 47 | class RtpRtcp; |
| 48 | class RtpTransportControllerSendInterface; |
| 49 | |
| 50 | struct SenderInfo; |
| 51 | |
| 52 | struct CallSendStatistics { |
| 53 | int64_t rttMs; |
| 54 | size_t bytesSent; |
| 55 | int packetsSent; |
| 56 | }; |
| 57 | |
| 58 | // See section 6.4.2 in http://www.ietf.org/rfc/rfc3550.txt for details. |
| 59 | struct ReportBlock { |
| 60 | uint32_t sender_SSRC; // SSRC of sender |
| 61 | uint32_t source_SSRC; |
| 62 | uint8_t fraction_lost; |
| 63 | int32_t cumulative_num_packets_lost; |
| 64 | uint32_t extended_highest_sequence_number; |
| 65 | uint32_t interarrival_jitter; |
| 66 | uint32_t last_SR_timestamp; |
| 67 | uint32_t delay_since_last_SR; |
| 68 | }; |
| 69 | |
| 70 | namespace voe { |
| 71 | |
| 72 | class RtpPacketSenderProxy; |
| 73 | class TransportFeedbackProxy; |
| 74 | class TransportSequenceNumberProxy; |
| 75 | class VoERtcpObserver; |
| 76 | |
| 77 | // Helper class to simplify locking scheme for members that are accessed from |
| 78 | // multiple threads. |
| 79 | // Example: a member can be set on thread T1 and read by an internal audio |
| 80 | // thread T2. Accessing the member via this class ensures that we are |
| 81 | // safe and also avoid TSan v2 warnings. |
| 82 | class ChannelSendState { |
| 83 | public: |
| 84 | struct State { |
| 85 | bool sending = false; |
| 86 | }; |
| 87 | |
| 88 | ChannelSendState() {} |
| 89 | virtual ~ChannelSendState() {} |
| 90 | |
| 91 | void Reset() { |
| 92 | rtc::CritScope lock(&lock_); |
| 93 | state_ = State(); |
| 94 | } |
| 95 | |
| 96 | State Get() const { |
| 97 | rtc::CritScope lock(&lock_); |
| 98 | return state_; |
| 99 | } |
| 100 | |
| 101 | void SetSending(bool enable) { |
| 102 | rtc::CritScope lock(&lock_); |
| 103 | state_.sending = enable; |
| 104 | } |
| 105 | |
| 106 | private: |
| 107 | rtc::CriticalSection lock_; |
| 108 | State state_; |
| 109 | }; |
| 110 | |
| 111 | class ChannelSend |
| 112 | : public Transport, |
| 113 | public AudioPacketizationCallback, // receive encoded packets from the |
| 114 | // ACM |
| 115 | public OverheadObserver { |
| 116 | public: |
| 117 | // TODO(nisse): Make OnUplinkPacketLossRate public, and delete friend |
| 118 | // declaration. |
| 119 | friend class VoERtcpObserver; |
| 120 | |
| 121 | ChannelSend(rtc::TaskQueue* encoder_queue, |
| 122 | ProcessThread* module_process_thread, |
Niels Möller | 7d76a31 | 2018-10-26 12:57:07 +0200 | [diff] [blame] | 123 | MediaTransportInterface* media_transport, |
Niels Möller | 530ead4 | 2018-10-04 14:28:39 +0200 | [diff] [blame] | 124 | RtcpRttStats* rtcp_rtt_stats, |
Benjamin Wright | 84583f6 | 2018-10-04 14:22:34 -0700 | [diff] [blame] | 125 | RtcEventLog* rtc_event_log, |
Benjamin Wright | bfb444c | 2018-10-15 10:20:24 -0700 | [diff] [blame] | 126 | FrameEncryptorInterface* frame_encryptor, |
Johannes Kron | 9190b82 | 2018-10-29 11:22:05 +0100 | [diff] [blame] | 127 | const webrtc::CryptoOptions& crypto_options, |
Jiawei Ou | 5571812 | 2018-11-09 13:17:39 -0800 | [diff] [blame^] | 128 | bool extmap_allow_mixed, |
| 129 | int rtcp_report_interval_ms); |
Niels Möller | 530ead4 | 2018-10-04 14:28:39 +0200 | [diff] [blame] | 130 | |
| 131 | virtual ~ChannelSend(); |
| 132 | |
| 133 | // Send using this encoder, with this payload type. |
| 134 | bool SetEncoder(int payload_type, std::unique_ptr<AudioEncoder> encoder); |
| 135 | void ModifyEncoder( |
| 136 | rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier); |
| 137 | |
| 138 | // API methods |
| 139 | |
| 140 | // VoEBase |
| 141 | int32_t StartSend(); |
| 142 | void StopSend(); |
| 143 | |
| 144 | // Codecs |
| 145 | void SetBitRate(int bitrate_bps, int64_t probing_interval_ms); |
Sebastian Jansson | 359d60a | 2018-10-25 16:22:02 +0200 | [diff] [blame] | 146 | int GetBitRate() const; |
Niels Möller | 530ead4 | 2018-10-04 14:28:39 +0200 | [diff] [blame] | 147 | bool EnableAudioNetworkAdaptor(const std::string& config_string); |
| 148 | void DisableAudioNetworkAdaptor(); |
| 149 | |
| 150 | // TODO(nisse): Modifies decoder, but not used? |
| 151 | void SetReceiverFrameLengthRange(int min_frame_length_ms, |
| 152 | int max_frame_length_ms); |
| 153 | |
| 154 | // Network |
| 155 | void RegisterTransport(Transport* transport); |
| 156 | // TODO(nisse, solenberg): Delete when VoENetwork is deleted. |
| 157 | int32_t ReceivedRTCPPacket(const uint8_t* data, size_t length); |
| 158 | |
| 159 | // Muting, Volume and Level. |
| 160 | void SetInputMute(bool enable); |
| 161 | |
| 162 | // Stats. |
| 163 | ANAStats GetANAStatistics() const; |
| 164 | |
| 165 | // Used by AudioSendStream. |
| 166 | RtpRtcp* GetRtpRtcp() const; |
| 167 | |
| 168 | // DTMF. |
| 169 | int SendTelephoneEventOutband(int event, int duration_ms); |
| 170 | int SetSendTelephoneEventPayloadType(int payload_type, int payload_frequency); |
| 171 | |
| 172 | // RTP+RTCP |
| 173 | int SetLocalSSRC(unsigned int ssrc); |
| 174 | |
| 175 | void SetMid(const std::string& mid, int extension_id); |
Johannes Kron | 9190b82 | 2018-10-29 11:22:05 +0100 | [diff] [blame] | 176 | void SetExtmapAllowMixed(bool extmap_allow_mixed); |
Niels Möller | 530ead4 | 2018-10-04 14:28:39 +0200 | [diff] [blame] | 177 | int SetSendAudioLevelIndicationStatus(bool enable, unsigned char id); |
| 178 | void EnableSendTransportSequenceNumber(int id); |
| 179 | |
| 180 | void RegisterSenderCongestionControlObjects( |
| 181 | RtpTransportControllerSendInterface* transport, |
| 182 | RtcpBandwidthObserver* bandwidth_observer); |
| 183 | void ResetSenderCongestionControlObjects(); |
| 184 | void SetRTCPStatus(bool enable); |
| 185 | int SetRTCP_CNAME(const char cName[256]); |
| 186 | int GetRemoteRTCPReportBlocks(std::vector<ReportBlock>* report_blocks); |
| 187 | int GetRTPStatistics(CallSendStatistics& stats); // NOLINT |
| 188 | void SetNACKStatus(bool enable, int maxNumberOfPackets); |
| 189 | |
| 190 | // From AudioPacketizationCallback in the ACM |
| 191 | int32_t SendData(FrameType frameType, |
| 192 | uint8_t payloadType, |
| 193 | uint32_t timeStamp, |
| 194 | const uint8_t* payloadData, |
| 195 | size_t payloadSize, |
| 196 | const RTPFragmentationHeader* fragmentation) override; |
| 197 | |
| 198 | // From Transport (called by the RTP/RTCP module) |
| 199 | bool SendRtp(const uint8_t* data, |
| 200 | size_t len, |
| 201 | const PacketOptions& packet_options) override; |
| 202 | bool SendRtcp(const uint8_t* data, size_t len) override; |
| 203 | |
| 204 | int PreferredSampleRate() const; |
| 205 | |
| 206 | bool Sending() const { return channel_state_.Get().sending; } |
| 207 | RtpRtcp* RtpRtcpModulePtr() const { return _rtpRtcpModule.get(); } |
| 208 | |
| 209 | // ProcessAndEncodeAudio() posts a task on the shared encoder task queue, |
| 210 | // which in turn calls (on the queue) ProcessAndEncodeAudioOnTaskQueue() where |
| 211 | // the actual processing of the audio takes place. The processing mainly |
| 212 | // consists of encoding and preparing the result for sending by adding it to a |
| 213 | // send queue. |
| 214 | // The main reason for using a task queue here is to release the native, |
| 215 | // OS-specific, audio capture thread as soon as possible to ensure that it |
| 216 | // can go back to sleep and be prepared to deliver an new captured audio |
| 217 | // packet. |
| 218 | void ProcessAndEncodeAudio(std::unique_ptr<AudioFrame> audio_frame); |
| 219 | |
| 220 | void SetTransportOverhead(size_t transport_overhead_per_packet); |
| 221 | |
| 222 | // From OverheadObserver in the RTP/RTCP module |
| 223 | void OnOverheadChanged(size_t overhead_bytes_per_packet) override; |
| 224 | |
| 225 | // The existence of this function alongside OnUplinkPacketLossRate is |
| 226 | // a compromise. We want the encoder to be agnostic of the PLR source, but |
| 227 | // we also don't want it to receive conflicting information from TWCC and |
| 228 | // from RTCP-XR. |
| 229 | void OnTwccBasedUplinkPacketLossRate(float packet_loss_rate); |
| 230 | |
| 231 | void OnRecoverableUplinkPacketLossRate(float recoverable_packet_loss_rate); |
| 232 | |
| 233 | int64_t GetRTT() const; |
| 234 | |
Benjamin Wright | 84583f6 | 2018-10-04 14:22:34 -0700 | [diff] [blame] | 235 | // E2EE Custom Audio Frame Encryption |
Benjamin Wright | 78410ad | 2018-10-25 09:52:57 -0700 | [diff] [blame] | 236 | void SetFrameEncryptor( |
| 237 | rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor); |
Benjamin Wright | 84583f6 | 2018-10-04 14:22:34 -0700 | [diff] [blame] | 238 | |
Niels Möller | 530ead4 | 2018-10-04 14:28:39 +0200 | [diff] [blame] | 239 | private: |
| 240 | class ProcessAndEncodeAudioTask; |
| 241 | |
| 242 | void Init(); |
| 243 | void Terminate(); |
| 244 | |
| 245 | void OnUplinkPacketLossRate(float packet_loss_rate); |
| 246 | bool InputMute() const; |
| 247 | |
| 248 | int ResendPackets(const uint16_t* sequence_numbers, int length); |
| 249 | |
| 250 | int SetSendRtpHeaderExtension(bool enable, |
| 251 | RTPExtensionType type, |
| 252 | unsigned char id); |
| 253 | |
| 254 | void UpdateOverheadForEncoder() |
| 255 | RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_); |
| 256 | |
| 257 | int GetRtpTimestampRateHz() const; |
| 258 | |
Niels Möller | 7d76a31 | 2018-10-26 12:57:07 +0200 | [diff] [blame] | 259 | int32_t SendRtpAudio(FrameType frameType, |
| 260 | uint8_t payloadType, |
| 261 | uint32_t timeStamp, |
| 262 | rtc::ArrayView<const uint8_t> payload, |
| 263 | const RTPFragmentationHeader* fragmentation); |
| 264 | |
| 265 | int32_t SendMediaTransportAudio(FrameType frameType, |
| 266 | uint8_t payloadType, |
| 267 | uint32_t timeStamp, |
| 268 | rtc::ArrayView<const uint8_t> payload, |
| 269 | const RTPFragmentationHeader* fragmentation); |
| 270 | |
| 271 | // Return media transport or nullptr if using RTP. |
| 272 | MediaTransportInterface* media_transport() { return media_transport_; } |
| 273 | |
Niels Möller | 530ead4 | 2018-10-04 14:28:39 +0200 | [diff] [blame] | 274 | // Called on the encoder task queue when a new input audio frame is ready |
| 275 | // for encoding. |
| 276 | void ProcessAndEncodeAudioOnTaskQueue(AudioFrame* audio_input); |
| 277 | |
| 278 | rtc::CriticalSection _callbackCritSect; |
| 279 | rtc::CriticalSection volume_settings_critsect_; |
| 280 | |
| 281 | ChannelSendState channel_state_; |
| 282 | |
| 283 | RtcEventLog* const event_log_; |
| 284 | |
| 285 | std::unique_ptr<RtpRtcp> _rtpRtcpModule; |
| 286 | |
| 287 | std::unique_ptr<AudioCodingModule> audio_coding_; |
| 288 | uint32_t _timeStamp RTC_GUARDED_BY(encoder_queue_); |
| 289 | |
| 290 | uint16_t send_sequence_number_; |
| 291 | |
| 292 | // uses |
| 293 | ProcessThread* _moduleProcessThreadPtr; |
| 294 | Transport* _transportPtr; // WebRtc socket or external transport |
| 295 | RmsLevel rms_level_ RTC_GUARDED_BY(encoder_queue_); |
| 296 | bool input_mute_ RTC_GUARDED_BY(volume_settings_critsect_); |
| 297 | bool previous_frame_muted_ RTC_GUARDED_BY(encoder_queue_); |
| 298 | // VoeRTP_RTCP |
| 299 | // TODO(henrika): can today be accessed on the main thread and on the |
| 300 | // task queue; hence potential race. |
| 301 | bool _includeAudioLevelIndication; |
| 302 | size_t transport_overhead_per_packet_ |
| 303 | RTC_GUARDED_BY(overhead_per_packet_lock_); |
| 304 | size_t rtp_overhead_per_packet_ RTC_GUARDED_BY(overhead_per_packet_lock_); |
| 305 | rtc::CriticalSection overhead_per_packet_lock_; |
| 306 | // RtcpBandwidthObserver |
| 307 | std::unique_ptr<VoERtcpObserver> rtcp_observer_; |
| 308 | |
| 309 | PacketRouter* packet_router_ = nullptr; |
| 310 | std::unique_ptr<TransportFeedbackProxy> feedback_observer_proxy_; |
| 311 | std::unique_ptr<TransportSequenceNumberProxy> seq_num_allocator_proxy_; |
| 312 | std::unique_ptr<RtpPacketSenderProxy> rtp_packet_sender_proxy_; |
| 313 | std::unique_ptr<RateLimiter> retransmission_rate_limiter_; |
| 314 | |
| 315 | rtc::ThreadChecker construction_thread_; |
| 316 | |
| 317 | const bool use_twcc_plr_for_ana_; |
| 318 | |
| 319 | rtc::CriticalSection encoder_queue_lock_; |
| 320 | bool encoder_queue_is_active_ RTC_GUARDED_BY(encoder_queue_lock_) = false; |
| 321 | rtc::TaskQueue* encoder_queue_ = nullptr; |
Benjamin Wright | 84583f6 | 2018-10-04 14:22:34 -0700 | [diff] [blame] | 322 | |
Niels Möller | 7d76a31 | 2018-10-26 12:57:07 +0200 | [diff] [blame] | 323 | MediaTransportInterface* const media_transport_; |
| 324 | int media_transport_sequence_number_ RTC_GUARDED_BY(encoder_queue_) = 0; |
| 325 | |
| 326 | rtc::CriticalSection media_transport_lock_; |
| 327 | // Currently set by SetLocalSSRC. |
| 328 | uint64_t media_transport_channel_id_ RTC_GUARDED_BY(&media_transport_lock_) = |
| 329 | 0; |
| 330 | // Cache payload type and sampling frequency from most recent call to |
| 331 | // SetEncoder. Needed to set MediaTransportEncodedAudioFrame metadata, and |
| 332 | // invalidate on encoder change. |
| 333 | int media_transport_payload_type_ RTC_GUARDED_BY(&media_transport_lock_); |
| 334 | int media_transport_sampling_frequency_ |
| 335 | RTC_GUARDED_BY(&media_transport_lock_); |
| 336 | |
Benjamin Wright | 84583f6 | 2018-10-04 14:22:34 -0700 | [diff] [blame] | 337 | // E2EE Audio Frame Encryption |
Benjamin Wright | 78410ad | 2018-10-25 09:52:57 -0700 | [diff] [blame] | 338 | rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor_; |
Benjamin Wright | bfb444c | 2018-10-15 10:20:24 -0700 | [diff] [blame] | 339 | // E2EE Frame Encryption Options |
| 340 | webrtc::CryptoOptions crypto_options_; |
Sebastian Jansson | 359d60a | 2018-10-25 16:22:02 +0200 | [diff] [blame] | 341 | int configured_bitrate_bps_ = 0; |
Niels Möller | 530ead4 | 2018-10-04 14:28:39 +0200 | [diff] [blame] | 342 | }; |
| 343 | |
| 344 | } // namespace voe |
| 345 | } // namespace webrtc |
| 346 | |
| 347 | #endif // AUDIO_CHANNEL_SEND_H_ |