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 MODULES_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H_ 12 #define MODULES_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H_ 13 14 #include "modules/audio_device/include/audio_device.h" 15 #include "rtc_base/buffer.h" 16 #include "rtc_base/criticalsection.h" 17 #include "rtc_base/task_queue.h" 18 #include "rtc_base/thread_annotations.h" 19 #include "rtc_base/thread_checker.h" 20 #include "system_wrappers/include/file_wrapper.h" 21 #include "typedefs.h" // NOLINT(build/include) 22 23 namespace webrtc { 24 25 // Delta times between two successive playout callbacks are limited to this 26 // value before added to an internal array. 27 const size_t kMaxDeltaTimeInMs = 500; 28 // TODO(henrika): remove when no longer used by external client. 29 const size_t kMaxBufferSizeBytes = 3840; // 10ms in stereo @ 96kHz 30 31 class AudioDeviceBuffer { 32 public: 33 enum LogState { 34 LOG_START = 0, 35 LOG_STOP, 36 LOG_ACTIVE, 37 }; 38 39 struct Stats { ResetRecStatsStats40 void ResetRecStats() { 41 rec_callbacks = 0; 42 rec_samples = 0; 43 max_rec_level = 0; 44 } 45 ResetPlayStatsStats46 void ResetPlayStats() { 47 play_callbacks = 0; 48 play_samples = 0; 49 max_play_level = 0; 50 } 51 52 // Total number of recording callbacks where the source provides 10ms audio 53 // data each time. 54 uint64_t rec_callbacks = 0; 55 56 // Total number of playback callbacks where the sink asks for 10ms audio 57 // data each time. 58 uint64_t play_callbacks = 0; 59 60 // Total number of recorded audio samples. 61 uint64_t rec_samples = 0; 62 63 // Total number of played audio samples. 64 uint64_t play_samples = 0; 65 66 // Contains max level (max(abs(x))) of recorded audio packets over the last 67 // 10 seconds where a new measurement is done twice per second. The level 68 // is reset to zero at each call to LogStats(). 69 int16_t max_rec_level = 0; 70 71 // Contains max level of recorded audio packets over the last 10 seconds 72 // where a new measurement is done twice per second. 73 int16_t max_play_level = 0; 74 }; 75 76 AudioDeviceBuffer(); 77 virtual ~AudioDeviceBuffer(); 78 79 int32_t RegisterAudioCallback(AudioTransport* audio_callback); 80 81 void StartPlayout(); 82 void StartRecording(); 83 void StopPlayout(); 84 void StopRecording(); 85 86 int32_t SetRecordingSampleRate(uint32_t fsHz); 87 int32_t SetPlayoutSampleRate(uint32_t fsHz); 88 int32_t RecordingSampleRate() const; 89 int32_t PlayoutSampleRate() const; 90 91 int32_t SetRecordingChannels(size_t channels); 92 int32_t SetPlayoutChannels(size_t channels); 93 size_t RecordingChannels() const; 94 size_t PlayoutChannels() const; 95 96 virtual int32_t SetRecordedBuffer(const void* audio_buffer, 97 size_t samples_per_channel); 98 int32_t SetCurrentMicLevel(uint32_t level); 99 virtual void SetVQEData(int play_delay_ms, int rec_delay_ms, int clock_drift); 100 virtual int32_t DeliverRecordedData(); 101 uint32_t NewMicLevel() const; 102 103 virtual int32_t RequestPlayoutData(size_t samples_per_channel); 104 virtual int32_t GetPlayoutData(void* audio_buffer); 105 106 int32_t SetTypingStatus(bool typing_status); 107 108 // Called on iOS where the native audio layer can be interrupted by other 109 // audio applications. This method can then be used to reset internal 110 // states and detach thread checkers to allow for a new audio session where 111 // native callbacks may come from a new set of I/O threads. 112 void NativeAudioInterrupted(); 113 114 private: 115 // Starts/stops periodic logging of audio stats. 116 void StartPeriodicLogging(); 117 void StopPeriodicLogging(); 118 119 // Called periodically on the internal thread created by the TaskQueue. 120 // Updates some stats but dooes it on the task queue to ensure that access of 121 // members is serialized hence avoiding usage of locks. 122 // state = LOG_START => members are initialized and the timer starts. 123 // state = LOG_STOP => no logs are printed and the timer stops. 124 // state = LOG_ACTIVE => logs are printed and the timer is kept alive. 125 void LogStats(LogState state); 126 127 // Updates counters in each play/record callback. These counters are later 128 // (periodically) read by LogStats() using a lock. 129 void UpdateRecStats(int16_t max_abs, size_t samples_per_channel); 130 void UpdatePlayStats(int16_t max_abs, size_t samples_per_channel); 131 132 // Clears all members tracking stats for recording and playout. 133 // These methods both run on the task queue. 134 void ResetRecStats(); 135 void ResetPlayStats(); 136 137 // This object lives on the main (creating) thread and most methods are 138 // called on that same thread. When audio has started some methods will be 139 // called on either a native audio thread for playout or a native thread for 140 // recording. Some members are not annotated since they are "protected by 141 // design" and adding e.g. a race checker can cause failuries for very few 142 // edge cases and it is IMHO not worth the risk to use them in this class. 143 // TODO(henrika): see if it is possible to refactor and annotate all members. 144 145 // Main thread on which this object is created. 146 rtc::ThreadChecker main_thread_checker_; 147 148 // Native (platform specific) audio thread driving the playout side. 149 rtc::ThreadChecker playout_thread_checker_; 150 151 // Native (platform specific) audio thread driving the recording side. 152 rtc::ThreadChecker recording_thread_checker_; 153 154 rtc::CriticalSection lock_; 155 156 // Task queue used to invoke LogStats() periodically. Tasks are executed on a 157 // worker thread but it does not necessarily have to be the same thread for 158 // each task. 159 rtc::TaskQueue task_queue_; 160 161 // Raw pointer to AudioTransport instance. Supplied to RegisterAudioCallback() 162 // and it must outlive this object. It is not possible to change this member 163 // while any media is active. It is possible to start media without calling 164 // RegisterAudioCallback() but that will lead to ignored audio callbacks in 165 // both directions where native audio will be acive but no audio samples will 166 // be transported. 167 AudioTransport* audio_transport_cb_; 168 169 // The members below that are not annotated are protected by design. They are 170 // all set on the main thread (verified by |main_thread_checker_|) and then 171 // read on either the playout or recording audio thread. But, media will never 172 // be active when the member is set; hence no conflict exists. It is too 173 // complex to ensure and verify that this is actually the case. 174 175 // Sample rate in Hertz. 176 uint32_t rec_sample_rate_; 177 uint32_t play_sample_rate_; 178 179 // Number of audio channels. 180 size_t rec_channels_; 181 size_t play_channels_; 182 183 // Keeps track of if playout/recording are active or not. A combination 184 // of these states are used to determine when to start and stop the timer. 185 // Only used on the creating thread and not used to control any media flow. 186 bool playing_ RTC_ACCESS_ON(main_thread_checker_); 187 bool recording_ RTC_ACCESS_ON(main_thread_checker_); 188 189 // Buffer used for audio samples to be played out. Size can be changed 190 // dynamically. The 16-bit samples are interleaved, hence the size is 191 // proportional to the number of channels. 192 rtc::BufferT<int16_t> play_buffer_ RTC_ACCESS_ON(playout_thread_checker_); 193 194 // Byte buffer used for recorded audio samples. Size can be changed 195 // dynamically. 196 rtc::BufferT<int16_t> rec_buffer_ RTC_ACCESS_ON(recording_thread_checker_); 197 198 // AGC parameters. 199 #if !defined(WEBRTC_WIN) 200 uint32_t current_mic_level_ RTC_ACCESS_ON(recording_thread_checker_); 201 #else 202 // Windows uses a dedicated thread for volume APIs. 203 uint32_t current_mic_level_; 204 #endif 205 uint32_t new_mic_level_ RTC_ACCESS_ON(recording_thread_checker_); 206 207 // Contains true of a key-press has been detected. 208 bool typing_status_ RTC_ACCESS_ON(recording_thread_checker_); 209 210 // Delay values used by the AEC. 211 int play_delay_ms_ RTC_ACCESS_ON(recording_thread_checker_); 212 int rec_delay_ms_ RTC_ACCESS_ON(recording_thread_checker_); 213 214 // Contains a clock-drift measurement. 215 int clock_drift_ RTC_ACCESS_ON(recording_thread_checker_); 216 217 // Counts number of times LogStats() has been called. 218 size_t num_stat_reports_ RTC_ACCESS_ON(task_queue_); 219 220 // Time stamp of last timer task (drives logging). 221 int64_t last_timer_task_time_ RTC_ACCESS_ON(task_queue_); 222 223 // Counts number of audio callbacks modulo 50 to create a signal when 224 // a new storage of audio stats shall be done. 225 int16_t rec_stat_count_ RTC_ACCESS_ON(recording_thread_checker_); 226 int16_t play_stat_count_ RTC_ACCESS_ON(playout_thread_checker_); 227 228 // Time stamps of when playout and recording starts. 229 int64_t play_start_time_ RTC_ACCESS_ON(main_thread_checker_); 230 int64_t rec_start_time_ RTC_ACCESS_ON(main_thread_checker_); 231 232 // Contains counters for playout and recording statistics. 233 Stats stats_ RTC_GUARDED_BY(lock_); 234 235 // Stores current stats at each timer task. Used to calculate differences 236 // between two successive timer events. 237 Stats last_stats_ RTC_ACCESS_ON(task_queue_); 238 239 // Set to true at construction and modified to false as soon as one audio- 240 // level estimate larger than zero is detected. 241 bool only_silence_recorded_; 242 243 // Set to true when logging of audio stats is enabled for the first time in 244 // StartPeriodicLogging() and set to false by StopPeriodicLogging(). 245 // Setting this member to false prevents (possiby invalid) log messages from 246 // being printed in the LogStats() task. 247 bool log_stats_ RTC_ACCESS_ON(task_queue_); 248 249 // Should *never* be defined in production builds. Only used for testing. 250 // When defined, the output signal will be replaced by a sinus tone at 440Hz. 251 #ifdef AUDIO_DEVICE_PLAYS_SINUS_TONE 252 double phase_ RTC_ACCESS_ON(playout_thread_checker_); 253 #endif 254 }; 255 256 } // namespace webrtc 257 258 #endif // MODULES_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H_ 259