Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: webrtc/modules/audio_device/audio_device_buffer.cc

Issue 2256833003: Cleanup of the AudioDeviceBuffer class (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: More changes Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include <algorithm> 11 #include <algorithm>
12 12
13 #include "webrtc/modules/audio_device/audio_device_buffer.h" 13 #include "webrtc/modules/audio_device/audio_device_buffer.h"
14 14
15 #include "webrtc/base/arraysize.h" 15 #include "webrtc/base/arraysize.h"
16 #include "webrtc/base/bind.h" 16 #include "webrtc/base/bind.h"
17 #include "webrtc/base/checks.h" 17 #include "webrtc/base/checks.h"
18 #include "webrtc/base/logging.h" 18 #include "webrtc/base/logging.h"
19 #include "webrtc/base/format_macros.h" 19 #include "webrtc/base/format_macros.h"
20 #include "webrtc/base/timeutils.h" 20 #include "webrtc/base/timeutils.h"
21 #include "webrtc/modules/audio_device/audio_device_config.h" 21 #include "webrtc/modules/audio_device/audio_device_config.h"
22 22
23 namespace webrtc { 23 namespace webrtc {
24 24
25 static const int kHighDelayThresholdMs = 300;
26 static const int kLogHighDelayIntervalFrames = 500; // 5 seconds.
27
28 static const char kTimerQueueName[] = "AudioDeviceBufferTimer"; 25 static const char kTimerQueueName[] = "AudioDeviceBufferTimer";
29 26
30 // Time between two sucessive calls to LogStats(). 27 // Time between two sucessive calls to LogStats().
31 static const size_t kTimerIntervalInSeconds = 10; 28 static const size_t kTimerIntervalInSeconds = 10;
32 static const size_t kTimerIntervalInMilliseconds = 29 static const size_t kTimerIntervalInMilliseconds =
33 kTimerIntervalInSeconds * rtc::kNumMillisecsPerSec; 30 kTimerIntervalInSeconds * rtc::kNumMillisecsPerSec;
34 31
35 AudioDeviceBuffer::AudioDeviceBuffer() 32 AudioDeviceBuffer::AudioDeviceBuffer()
36 : _ptrCbAudioTransport(nullptr), 33 : audio_transport_cb_(nullptr),
37 task_queue_(kTimerQueueName), 34 task_queue_(kTimerQueueName),
38 timer_has_started_(false), 35 timer_has_started_(false),
39 _recSampleRate(0), 36 rec_sample_rate_(0),
40 _playSampleRate(0), 37 play_sample_rate_(0),
41 _recChannels(0), 38 rec_channels_(0),
42 _playChannels(0), 39 play_channels_(0),
43 _recChannel(AudioDeviceModule::kChannelBoth), 40 rec_channel_(AudioDeviceModule::kChannelBoth),
44 _recBytesPerSample(0), 41 rec_bytes_per_sample_(0),
45 _playBytesPerSample(0), 42 play_bytes_per_sample_(0),
46 _recSamples(0), 43 rec_samples_per_10ms_(0),
47 _recSize(0), 44 rec_bytes_per_10ms_(0),
48 _playSamples(0), 45 play_samples_per_10ms_(0),
49 _playSize(0), 46 play_bytes_per_10ms_(0),
50 _recFile(*FileWrapper::Create()), 47 current_mic_level_(0),
51 _playFile(*FileWrapper::Create()), 48 new_mic_level_(0),
52 _currentMicLevel(0), 49 typing_status_(false),
53 _newMicLevel(0), 50 play_delay_ms_(0),
54 _typingStatus(false), 51 rec_delay_ms_(0),
55 _playDelayMS(0), 52 clock_drift_(0),
56 _recDelayMS(0),
57 _clockDrift(0),
58 // Set to the interval in order to log on the first occurrence.
59 high_delay_counter_(kLogHighDelayIntervalFrames),
60 num_stat_reports_(0), 53 num_stat_reports_(0),
61 rec_callbacks_(0), 54 rec_callbacks_(0),
62 last_rec_callbacks_(0), 55 last_rec_callbacks_(0),
63 play_callbacks_(0), 56 play_callbacks_(0),
64 last_play_callbacks_(0), 57 last_play_callbacks_(0),
65 rec_samples_(0), 58 rec_samples_(0),
66 last_rec_samples_(0), 59 last_rec_samples_(0),
67 play_samples_(0), 60 play_samples_(0),
68 last_play_samples_(0), 61 last_play_samples_(0),
69 last_log_stat_time_(0) { 62 last_log_stat_time_(0) {
70 LOG(INFO) << "AudioDeviceBuffer::ctor"; 63 LOG(INFO) << "AudioDeviceBuffer::ctor";
71 memset(_recBuffer, 0, kMaxBufferSizeBytes);
72 memset(_playBuffer, 0, kMaxBufferSizeBytes);
73 } 64 }
74 65
75 AudioDeviceBuffer::~AudioDeviceBuffer() { 66 AudioDeviceBuffer::~AudioDeviceBuffer() {
76 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 67 RTC_DCHECK(thread_checker_.CalledOnValidThread());
77 LOG(INFO) << "AudioDeviceBuffer::~dtor"; 68 LOG(INFO) << "AudioDeviceBuffer::~dtor";
78 69
79 size_t total_diff_time = 0; 70 size_t total_diff_time = 0;
80 int num_measurements = 0; 71 int num_measurements = 0;
81 LOG(INFO) << "[playout diff time => #measurements]"; 72 LOG(INFO) << "[playout diff time => #measurements]";
82 for (size_t diff = 0; diff < arraysize(playout_diff_times_); ++diff) { 73 for (size_t diff = 0; diff < arraysize(playout_diff_times_); ++diff) {
83 uint32_t num_elements = playout_diff_times_[diff]; 74 uint32_t num_elements = playout_diff_times_[diff];
84 if (num_elements > 0) { 75 if (num_elements > 0) {
85 total_diff_time += num_elements * diff; 76 total_diff_time += num_elements * diff;
86 num_measurements += num_elements; 77 num_measurements += num_elements;
87 LOG(INFO) << "[" << diff << " => " << num_elements << "]"; 78 LOG(INFO) << "[" << diff << " => " << num_elements << "]";
88 } 79 }
89 } 80 }
90 if (num_measurements > 0) { 81 if (num_measurements > 0) {
91 LOG(INFO) << "total_diff_time: " << total_diff_time; 82 LOG(INFO) << "total_diff_time: " << total_diff_time;
92 LOG(INFO) << "num_measurements: " << num_measurements; 83 LOG(INFO) << "num_measurements: " << num_measurements;
93 LOG(INFO) << "average: " 84 LOG(INFO) << "average: "
94 << static_cast<float>(total_diff_time) / num_measurements; 85 << static_cast<float>(total_diff_time) / num_measurements;
95 } 86 }
96
97 _recFile.Flush();
98 _recFile.CloseFile();
99 delete &_recFile;
100
101 _playFile.Flush();
102 _playFile.CloseFile();
103 delete &_playFile;
104 } 87 }
105 88
106 int32_t AudioDeviceBuffer::RegisterAudioCallback( 89 int32_t AudioDeviceBuffer::RegisterAudioCallback(
107 AudioTransport* audioCallback) { 90 AudioTransport* audioCallback) {
108 LOG(INFO) << __FUNCTION__; 91 LOG(INFO) << __FUNCTION__;
109 rtc::CritScope lock(&_critSectCb); 92 rtc::CritScope lock(&_critSectCb);
110 _ptrCbAudioTransport = audioCallback; 93 audio_transport_cb_ = audioCallback;
111 return 0; 94 return 0;
112 } 95 }
113 96
114 int32_t AudioDeviceBuffer::InitPlayout() { 97 int32_t AudioDeviceBuffer::InitPlayout() {
98 LOG(INFO) << __FUNCTION__;
115 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 99 RTC_DCHECK(thread_checker_.CalledOnValidThread());
116 LOG(INFO) << __FUNCTION__; 100 RTC_DCHECK(rec_sample_rate_);
101 RTC_DCHECK(rec_bytes_per_sample_);
117 last_playout_time_ = rtc::TimeMillis(); 102 last_playout_time_ = rtc::TimeMillis();
118 if (!timer_has_started_) { 103 if (!timer_has_started_) {
119 StartTimer(); 104 StartTimer();
120 timer_has_started_ = true; 105 timer_has_started_ = true;
121 } 106 }
107 // Derive the required buffer size given sample rate and number of channels.
108 play_samples_per_10ms_ = static_cast<size_t>(play_sample_rate_ * 10 / 1000);
109 play_bytes_per_10ms_ = play_bytes_per_sample_ * play_samples_per_10ms_;
110 LOG(INFO) << "playout samples per 10ms: " << play_samples_per_10ms_;
111 LOG(INFO) << "playout bytes per 10ms: " << play_bytes_per_10ms_;
112 // Allocate memory for the playout audio buffer. It will always contain audio
113 // samples corresponding to 10ms of audio to be played out.
114 play_buffer_.reset(new int8_t[play_bytes_per_10ms_]);
122 return 0; 115 return 0;
123 } 116 }
124 117
125 int32_t AudioDeviceBuffer::InitRecording() { 118 int32_t AudioDeviceBuffer::InitRecording() {
119 LOG(INFO) << __FUNCTION__;
126 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 120 RTC_DCHECK(thread_checker_.CalledOnValidThread());
127 LOG(INFO) << __FUNCTION__; 121 RTC_DCHECK(rec_sample_rate_);
122 RTC_DCHECK(rec_bytes_per_sample_);
128 if (!timer_has_started_) { 123 if (!timer_has_started_) {
129 StartTimer(); 124 StartTimer();
130 timer_has_started_ = true; 125 timer_has_started_ = true;
131 } 126 }
127 // Derive the required buffer size given sample rate and number of channels.
128 rec_samples_per_10ms_ = static_cast<size_t>(rec_sample_rate_ * 10 / 1000);
129 rec_bytes_per_10ms_ = rec_bytes_per_sample_ * rec_samples_per_10ms_;
130 LOG(INFO) << "recorded samples per 10ms: " << rec_samples_per_10ms_;
131 LOG(INFO) << "recorded bytes per 10ms: " << rec_bytes_per_10ms_;
132 // Allocate memory for the recording audio buffer. It will always contain
133 // audio samples corresponding to 10ms of audio.
134 rec_buffer_.reset(new int8_t[rec_bytes_per_10ms_]);
132 return 0; 135 return 0;
133 } 136 }
134 137
135 int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz) { 138 int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz) {
136 LOG(INFO) << "SetRecordingSampleRate(" << fsHz << ")"; 139 LOG(INFO) << "SetRecordingSampleRate(" << fsHz << ")";
137 rtc::CritScope lock(&_critSect); 140 rtc::CritScope lock(&_critSect);
138 _recSampleRate = fsHz; 141 rec_sample_rate_ = fsHz;
139 return 0; 142 return 0;
140 } 143 }
141 144
142 int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz) { 145 int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz) {
143 LOG(INFO) << "SetPlayoutSampleRate(" << fsHz << ")"; 146 LOG(INFO) << "SetPlayoutSampleRate(" << fsHz << ")";
144 rtc::CritScope lock(&_critSect); 147 rtc::CritScope lock(&_critSect);
145 _playSampleRate = fsHz; 148 play_sample_rate_ = fsHz;
146 return 0; 149 return 0;
147 } 150 }
148 151
149 int32_t AudioDeviceBuffer::RecordingSampleRate() const { 152 int32_t AudioDeviceBuffer::RecordingSampleRate() const {
150 return _recSampleRate; 153 return rec_sample_rate_;
151 } 154 }
152 155
153 int32_t AudioDeviceBuffer::PlayoutSampleRate() const { 156 int32_t AudioDeviceBuffer::PlayoutSampleRate() const {
154 return _playSampleRate; 157 return play_sample_rate_;
155 } 158 }
156 159
157 int32_t AudioDeviceBuffer::SetRecordingChannels(size_t channels) { 160 int32_t AudioDeviceBuffer::SetRecordingChannels(size_t channels) {
158 rtc::CritScope lock(&_critSect); 161 rtc::CritScope lock(&_critSect);
159 _recChannels = channels; 162 rec_channels_ = channels;
160 _recBytesPerSample = 163 rec_bytes_per_sample_ =
161 2 * channels; // 16 bits per sample in mono, 32 bits in stereo 164 2 * channels; // 16 bits per sample in mono, 32 bits in stereo
162 return 0; 165 return 0;
163 } 166 }
164 167
165 int32_t AudioDeviceBuffer::SetPlayoutChannels(size_t channels) { 168 int32_t AudioDeviceBuffer::SetPlayoutChannels(size_t channels) {
166 rtc::CritScope lock(&_critSect); 169 rtc::CritScope lock(&_critSect);
167 _playChannels = channels; 170 play_channels_ = channels;
168 // 16 bits per sample in mono, 32 bits in stereo 171 // 16 bits per sample in mono, 32 bits in stereo
169 _playBytesPerSample = 2 * channels; 172 play_bytes_per_sample_ = 2 * channels;
170 return 0; 173 return 0;
171 } 174 }
172 175
173 int32_t AudioDeviceBuffer::SetRecordingChannel( 176 int32_t AudioDeviceBuffer::SetRecordingChannel(
174 const AudioDeviceModule::ChannelType channel) { 177 const AudioDeviceModule::ChannelType channel) {
175 rtc::CritScope lock(&_critSect); 178 rtc::CritScope lock(&_critSect);
176 179
177 if (_recChannels == 1) { 180 if (rec_channels_ == 1) {
178 return -1; 181 return -1;
179 } 182 }
180 183
181 if (channel == AudioDeviceModule::kChannelBoth) { 184 if (channel == AudioDeviceModule::kChannelBoth) {
182 // two bytes per channel 185 // two bytes per channel
183 _recBytesPerSample = 4; 186 rec_bytes_per_sample_ = 4;
184 } else { 187 } else {
185 // only utilize one out of two possible channels (left or right) 188 // only utilize one out of two possible channels (left or right)
186 _recBytesPerSample = 2; 189 rec_bytes_per_sample_ = 2;
187 } 190 }
188 _recChannel = channel; 191 rec_channel_ = channel;
189 192
190 return 0; 193 return 0;
191 } 194 }
192 195
193 int32_t AudioDeviceBuffer::RecordingChannel( 196 int32_t AudioDeviceBuffer::RecordingChannel(
194 AudioDeviceModule::ChannelType& channel) const { 197 AudioDeviceModule::ChannelType& channel) const {
195 channel = _recChannel; 198 channel = rec_channel_;
196 return 0; 199 return 0;
197 } 200 }
198 201
199 size_t AudioDeviceBuffer::RecordingChannels() const { 202 size_t AudioDeviceBuffer::RecordingChannels() const {
200 return _recChannels; 203 return rec_channels_;
201 } 204 }
202 205
203 size_t AudioDeviceBuffer::PlayoutChannels() const { 206 size_t AudioDeviceBuffer::PlayoutChannels() const {
204 return _playChannels; 207 return play_channels_;
205 } 208 }
206 209
207 int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level) { 210 int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level) {
208 _currentMicLevel = level; 211 current_mic_level_ = level;
209 return 0; 212 return 0;
210 } 213 }
211 214
212 int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus) { 215 int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus) {
213 _typingStatus = typingStatus; 216 typing_status_ = typingStatus;
214 return 0; 217 return 0;
215 } 218 }
216 219
217 uint32_t AudioDeviceBuffer::NewMicLevel() const { 220 uint32_t AudioDeviceBuffer::NewMicLevel() const {
218 return _newMicLevel; 221 return new_mic_level_;
219 } 222 }
220 223
221 void AudioDeviceBuffer::SetVQEData(int playDelayMs, 224 void AudioDeviceBuffer::SetVQEData(int playDelayMs,
222 int recDelayMs, 225 int recDelayMs,
223 int clockDrift) { 226 int clockDrift) {
224 if (high_delay_counter_ < kLogHighDelayIntervalFrames) { 227 play_delay_ms_ = playDelayMs;
225 ++high_delay_counter_; 228 rec_delay_ms_ = recDelayMs;
226 } else { 229 clock_drift_ = clockDrift;
227 if (playDelayMs + recDelayMs > kHighDelayThresholdMs) {
228 high_delay_counter_ = 0;
229 LOG(LS_WARNING) << "High audio device delay reported (render="
230 << playDelayMs << " ms, capture=" << recDelayMs << " ms)";
231 }
232 }
233
234 _playDelayMS = playDelayMs;
235 _recDelayMS = recDelayMs;
236 _clockDrift = clockDrift;
237 } 230 }
238 231
239 int32_t AudioDeviceBuffer::StartInputFileRecording( 232 int32_t AudioDeviceBuffer::StartInputFileRecording(
240 const char fileName[kAdmMaxFileNameSize]) { 233 const char fileName[kAdmMaxFileNameSize]) {
241 rtc::CritScope lock(&_critSect); 234 FATAL() << "Should not be called";
242 235 return -1;
243 _recFile.Flush();
244 _recFile.CloseFile();
245
246 return _recFile.OpenFile(fileName, false) ? 0 : -1;
247 } 236 }
248 237
249 int32_t AudioDeviceBuffer::StopInputFileRecording() { 238 int32_t AudioDeviceBuffer::StopInputFileRecording() {
250 rtc::CritScope lock(&_critSect); 239 FATAL() << "Should not be called";
251 240 return -1;
252 _recFile.Flush();
253 _recFile.CloseFile();
254
255 return 0;
256 } 241 }
257 242
258 int32_t AudioDeviceBuffer::StartOutputFileRecording( 243 int32_t AudioDeviceBuffer::StartOutputFileRecording(
259 const char fileName[kAdmMaxFileNameSize]) { 244 const char fileName[kAdmMaxFileNameSize]) {
260 rtc::CritScope lock(&_critSect); 245 FATAL() << "Should not be called";
261 246 return -1;
262 _playFile.Flush();
263 _playFile.CloseFile();
264
265 return _playFile.OpenFile(fileName, false) ? 0 : -1;
266 } 247 }
267 248
268 int32_t AudioDeviceBuffer::StopOutputFileRecording() { 249 int32_t AudioDeviceBuffer::StopOutputFileRecording() {
250 FATAL() << "Should not be called";
251 return -1;
252 }
253
254 int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audio_buffer,
255 size_t num_samples) {
256 RTC_CHECK(rec_buffer_);
257 // WebRTC can only receive audio in 10ms chunks, hence we fail if the native
258 // audio layer tries to deliver something else.
259 RTC_CHECK_EQ(num_samples, rec_samples_per_10ms_);
260
269 rtc::CritScope lock(&_critSect); 261 rtc::CritScope lock(&_critSect);
270 262
271 _playFile.Flush(); 263 if (rec_channel_ == AudioDeviceModule::kChannelBoth) {
272 _playFile.CloseFile(); 264 // (default) copy the complete input buffer to the local buffer
265 memcpy(&rec_buffer_[0], audio_buffer, rec_bytes_per_10ms_);
266 } else {
267 int16_t* ptr16In = (int16_t*)audio_buffer;
268 int16_t* ptr16Out = (int16_t*)&rec_buffer_[0];
273 269
274 return 0; 270 if (AudioDeviceModule::kChannelRight == rec_channel_) {
275 }
276
277 int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer,
278 size_t nSamples) {
279 rtc::CritScope lock(&_critSect);
280
281 if (_recBytesPerSample == 0) {
282 assert(false);
283 return -1;
284 }
285
286 _recSamples = nSamples;
287 _recSize = _recBytesPerSample * nSamples; // {2,4}*nSamples
288 if (_recSize > kMaxBufferSizeBytes) {
289 assert(false);
290 return -1;
291 }
292
293 if (_recChannel == AudioDeviceModule::kChannelBoth) {
294 // (default) copy the complete input buffer to the local buffer
295 memcpy(&_recBuffer[0], audioBuffer, _recSize);
296 } else {
297 int16_t* ptr16In = (int16_t*)audioBuffer;
298 int16_t* ptr16Out = (int16_t*)&_recBuffer[0];
299
300 if (AudioDeviceModule::kChannelRight == _recChannel) {
301 ptr16In++; 271 ptr16In++;
302 } 272 }
303 273
304 // exctract left or right channel from input buffer to the local buffer 274 // exctract left or right channel from input buffer to the local buffer
305 for (size_t i = 0; i < _recSamples; i++) { 275 for (size_t i = 0; i < rec_samples_per_10ms_; i++) {
306 *ptr16Out = *ptr16In; 276 *ptr16Out = *ptr16In;
307 ptr16Out++; 277 ptr16Out++;
308 ptr16In++; 278 ptr16In++;
309 ptr16In++; 279 ptr16In++;
310 } 280 }
311 } 281 }
312 282
313 if (_recFile.is_open()) {
314 // write to binary file in mono or stereo (interleaved)
315 _recFile.Write(&_recBuffer[0], _recSize);
316 }
317
318 // Update some stats but do it on the task queue to ensure that the members 283 // Update some stats but do it on the task queue to ensure that the members
319 // are modified and read on the same thread. 284 // are modified and read on the same thread.
320 task_queue_.PostTask( 285 task_queue_.PostTask(
321 rtc::Bind(&AudioDeviceBuffer::UpdateRecStats, this, nSamples)); 286 rtc::Bind(&AudioDeviceBuffer::UpdateRecStats, this, num_samples));
322 287
323 return 0; 288 return 0;
324 } 289 }
325 290
326 int32_t AudioDeviceBuffer::DeliverRecordedData() { 291 int32_t AudioDeviceBuffer::DeliverRecordedData() {
292 RTC_CHECK(rec_buffer_);
293 RTC_DCHECK(audio_transport_cb_);
327 rtc::CritScope lock(&_critSectCb); 294 rtc::CritScope lock(&_critSectCb);
328 // Ensure that user has initialized all essential members
329 if ((_recSampleRate == 0) || (_recSamples == 0) ||
330 (_recBytesPerSample == 0) || (_recChannels == 0)) {
331 RTC_NOTREACHED();
332 return -1;
333 }
334 295
335 if (!_ptrCbAudioTransport) { 296 if (!audio_transport_cb_) {
336 LOG(LS_WARNING) << "Invalid audio transport"; 297 LOG(LS_WARNING) << "Invalid audio transport";
337 return 0; 298 return 0;
338 } 299 }
339 300
340 int32_t res(0); 301 int32_t res(0);
341 uint32_t newMicLevel(0); 302 uint32_t newMicLevel(0);
342 uint32_t totalDelayMS = _playDelayMS + _recDelayMS; 303 uint32_t totalDelayMS = play_delay_ms_ + rec_delay_ms_;
343 res = _ptrCbAudioTransport->RecordedDataIsAvailable( 304 res = audio_transport_cb_->RecordedDataIsAvailable(
344 &_recBuffer[0], _recSamples, _recBytesPerSample, _recChannels, 305 &rec_buffer_[0], rec_samples_per_10ms_, rec_bytes_per_sample_,
345 _recSampleRate, totalDelayMS, _clockDrift, _currentMicLevel, 306 rec_channels_, rec_sample_rate_, totalDelayMS, clock_drift_,
346 _typingStatus, newMicLevel); 307 current_mic_level_, typing_status_, newMicLevel);
347 if (res != -1) { 308 if (res != -1) {
348 _newMicLevel = newMicLevel; 309 new_mic_level_ = newMicLevel;
349 } 310 }
350 311
351 return 0; 312 return 0;
352 } 313 }
353 314
354 int32_t AudioDeviceBuffer::RequestPlayoutData(size_t nSamples) { 315 int32_t AudioDeviceBuffer::RequestPlayoutData(size_t num_samples) {
355 uint32_t playSampleRate = 0; 316 RTC_CHECK(play_buffer_);
356 size_t playBytesPerSample = 0; 317 // WebRTC can only provide audio in 10ms chunks, hence we fail if the native
357 size_t playChannels = 0; 318 // audio layer asks for something else.
319 RTC_CHECK_EQ(num_samples, play_samples_per_10ms_);
358 320
359 // Measure time since last function call and update an array where the 321 // Measure time since last function call and update an array where the
360 // position/index corresponds to time differences (in milliseconds) between 322 // position/index corresponds to time differences (in milliseconds) between
361 // two successive playout callbacks, and the stored value is the number of 323 // two successive playout callbacks, and the stored value is the number of
362 // times a given time difference was found. 324 // times a given time difference was found.
363 int64_t now_time = rtc::TimeMillis(); 325 int64_t now_time = rtc::TimeMillis();
364 size_t diff_time = rtc::TimeDiff(now_time, last_playout_time_); 326 size_t diff_time = rtc::TimeDiff(now_time, last_playout_time_);
365 // Truncate at 500ms to limit the size of the array. 327 // Truncate at 500ms to limit the size of the array.
366 diff_time = std::min(kMaxDeltaTimeInMs, diff_time); 328 diff_time = std::min(kMaxDeltaTimeInMs, diff_time);
367 last_playout_time_ = now_time; 329 last_playout_time_ = now_time;
368 playout_diff_times_[diff_time]++; 330 playout_diff_times_[diff_time]++;
369 331
370 // TOOD(henrika): improve bad locking model and make it more clear that only
371 // 10ms buffer sizes is supported in WebRTC.
372 {
373 rtc::CritScope lock(&_critSect);
374
375 // Store copies under lock and use copies hereafter to avoid race with
376 // setter methods.
377 playSampleRate = _playSampleRate;
378 playBytesPerSample = _playBytesPerSample;
379 playChannels = _playChannels;
380
381 // Ensure that user has initialized all essential members
382 if ((playBytesPerSample == 0) || (playChannels == 0) ||
383 (playSampleRate == 0)) {
384 RTC_NOTREACHED();
385 return -1;
386 }
387
388 _playSamples = nSamples;
389 _playSize = playBytesPerSample * nSamples; // {2,4}*nSamples
390 RTC_CHECK_LE(_playSize, kMaxBufferSizeBytes);
391 RTC_CHECK_EQ(nSamples, _playSamples);
392 }
393
394 size_t nSamplesOut(0);
395
396 rtc::CritScope lock(&_critSectCb); 332 rtc::CritScope lock(&_critSectCb);
397 333
398 // It is currently supported to start playout without a valid audio 334 // It is currently supported to start playout without a valid audio
399 // transport object. Leads to warning and silence. 335 // transport object. Leads to warning and silence.
400 if (!_ptrCbAudioTransport) { 336 if (!audio_transport_cb_) {
401 LOG(LS_WARNING) << "Invalid audio transport"; 337 LOG(LS_WARNING) << "Invalid audio transport";
402 return 0; 338 return 0;
403 } 339 }
404 340
405 uint32_t res(0); 341 uint32_t res(0);
406 int64_t elapsed_time_ms = -1; 342 int64_t elapsed_time_ms = -1;
407 int64_t ntp_time_ms = -1; 343 int64_t ntp_time_ms = -1;
408 res = _ptrCbAudioTransport->NeedMorePlayData( 344 size_t num_samples_out(0);
409 _playSamples, playBytesPerSample, playChannels, playSampleRate, 345 res = audio_transport_cb_->NeedMorePlayData(
410 &_playBuffer[0], nSamplesOut, &elapsed_time_ms, &ntp_time_ms); 346 play_samples_per_10ms_, play_bytes_per_sample_, play_channels_,
347 play_sample_rate_, &play_buffer_[0], num_samples_out, &elapsed_time_ms,
348 &ntp_time_ms);
411 if (res != 0) { 349 if (res != 0) {
412 LOG(LS_ERROR) << "NeedMorePlayData() failed"; 350 LOG(LS_ERROR) << "NeedMorePlayData() failed";
413 } 351 }
414 352
415 // Update some stats but do it on the task queue to ensure that access of 353 // Update some stats but do it on the task queue to ensure that access of
416 // members is serialized hence avoiding usage of locks. 354 // members is serialized hence avoiding usage of locks.
417 task_queue_.PostTask( 355 task_queue_.PostTask(
418 rtc::Bind(&AudioDeviceBuffer::UpdatePlayStats, this, nSamplesOut)); 356 rtc::Bind(&AudioDeviceBuffer::UpdatePlayStats, this, num_samples_out));
419 357
420 return static_cast<int32_t>(nSamplesOut); 358 RTC_DCHECK_EQ(num_samples, num_samples_out);
359 return static_cast<int32_t>(num_samples_out);
421 } 360 }
422 361
423 int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer) { 362 int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer) {
424 rtc::CritScope lock(&_critSect); 363 rtc::CritScope lock(&_critSect);
425 RTC_CHECK_LE(_playSize, kMaxBufferSizeBytes); 364 memcpy(audioBuffer, &play_buffer_[0], play_bytes_per_10ms_);
426 365 return static_cast<int32_t>(play_samples_per_10ms_);
427 memcpy(audioBuffer, &_playBuffer[0], _playSize);
428
429 if (_playFile.is_open()) {
430 // write to binary file in mono or stereo (interleaved)
431 _playFile.Write(&_playBuffer[0], _playSize);
432 }
433
434 return static_cast<int32_t>(_playSamples);
435 } 366 }
436 367
437 void AudioDeviceBuffer::StartTimer() { 368 void AudioDeviceBuffer::StartTimer() {
438 last_log_stat_time_ = rtc::TimeMillis(); 369 last_log_stat_time_ = rtc::TimeMillis();
439 task_queue_.PostDelayedTask(rtc::Bind(&AudioDeviceBuffer::LogStats, this), 370 task_queue_.PostDelayedTask(rtc::Bind(&AudioDeviceBuffer::LogStats, this),
440 kTimerIntervalInMilliseconds); 371 kTimerIntervalInMilliseconds);
441 } 372 }
442 373
443 void AudioDeviceBuffer::LogStats() { 374 void AudioDeviceBuffer::LogStats() {
444 RTC_DCHECK(task_queue_.IsCurrent()); 375 RTC_DCHECK(task_queue_.IsCurrent());
445 376
446 int64_t now_time = rtc::TimeMillis(); 377 int64_t now_time = rtc::TimeMillis();
447 int64_t next_callback_time = now_time + kTimerIntervalInMilliseconds; 378 int64_t next_callback_time = now_time + kTimerIntervalInMilliseconds;
448 int64_t time_since_last = rtc::TimeDiff(now_time, last_log_stat_time_); 379 int64_t time_since_last = rtc::TimeDiff(now_time, last_log_stat_time_);
449 last_log_stat_time_ = now_time; 380 last_log_stat_time_ = now_time;
450 381
451 // Log the latest statistics but skip the first 10 seconds since we are not 382 // Log the latest statistics but skip the first 10 seconds since we are not
452 // sure of the exact starting point. I.e., the first log printout will be 383 // sure of the exact starting point. I.e., the first log printout will be
453 // after ~20 seconds. 384 // after ~20 seconds.
454 if (++num_stat_reports_ > 1) { 385 if (++num_stat_reports_ > 1) {
455 uint32_t diff_samples = rec_samples_ - last_rec_samples_; 386 uint32_t diff_samples = rec_samples_ - last_rec_samples_;
456 uint32_t rate = diff_samples / kTimerIntervalInSeconds; 387 uint32_t rate = diff_samples / kTimerIntervalInSeconds;
457 LOG(INFO) << "[REC : " << time_since_last << "msec, " 388 LOG(INFO) << "[REC : " << time_since_last << "msec, "
458 << _recSampleRate / 1000 389 << rec_sample_rate_ / 1000
459 << "kHz] callbacks: " << rec_callbacks_ - last_rec_callbacks_ 390 << "kHz] callbacks: " << rec_callbacks_ - last_rec_callbacks_
460 << ", " 391 << ", "
461 << "samples: " << diff_samples << ", " 392 << "samples: " << diff_samples << ", "
462 << "rate: " << rate; 393 << "rate: " << rate;
463 394
464 diff_samples = play_samples_ - last_play_samples_; 395 diff_samples = play_samples_ - last_play_samples_;
465 rate = diff_samples / kTimerIntervalInSeconds; 396 rate = diff_samples / kTimerIntervalInSeconds;
466 LOG(INFO) << "[PLAY: " << time_since_last << "msec, " 397 LOG(INFO) << "[PLAY: " << time_since_last << "msec, "
467 << _playSampleRate / 1000 398 << play_sample_rate_ / 1000
468 << "kHz] callbacks: " << play_callbacks_ - last_play_callbacks_ 399 << "kHz] callbacks: " << play_callbacks_ - last_play_callbacks_
469 << ", " 400 << ", "
470 << "samples: " << diff_samples << ", " 401 << "samples: " << diff_samples << ", "
471 << "rate: " << rate; 402 << "rate: " << rate;
472 } 403 }
473 404
474 last_rec_callbacks_ = rec_callbacks_; 405 last_rec_callbacks_ = rec_callbacks_;
475 last_play_callbacks_ = play_callbacks_; 406 last_play_callbacks_ = play_callbacks_;
476 last_rec_samples_ = rec_samples_; 407 last_rec_samples_ = rec_samples_;
477 last_play_samples_ = play_samples_; 408 last_play_samples_ = play_samples_;
(...skipping 13 matching lines...) Expand all
491 rec_samples_ += num_samples; 422 rec_samples_ += num_samples;
492 } 423 }
493 424
494 void AudioDeviceBuffer::UpdatePlayStats(size_t num_samples) { 425 void AudioDeviceBuffer::UpdatePlayStats(size_t num_samples) {
495 RTC_DCHECK(task_queue_.IsCurrent()); 426 RTC_DCHECK(task_queue_.IsCurrent());
496 ++play_callbacks_; 427 ++play_callbacks_;
497 play_samples_ += num_samples; 428 play_samples_ += num_samples;
498 } 429 }
499 430
500 } // namespace webrtc 431 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698