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