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

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

Issue 2433393002: Avoids invalid copy of audio buffer to task queue (Closed)
Patch Set: nit Created 4 years, 2 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
« no previous file with comments | « webrtc/modules/audio_device/audio_device_buffer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 last_rec_callbacks_(0), 52 last_rec_callbacks_(0),
53 play_callbacks_(0), 53 play_callbacks_(0),
54 last_play_callbacks_(0), 54 last_play_callbacks_(0),
55 rec_samples_(0), 55 rec_samples_(0),
56 last_rec_samples_(0), 56 last_rec_samples_(0),
57 play_samples_(0), 57 play_samples_(0),
58 last_play_samples_(0), 58 last_play_samples_(0),
59 last_log_stat_time_(0), 59 last_log_stat_time_(0),
60 max_rec_level_(0), 60 max_rec_level_(0),
61 max_play_level_(0), 61 max_play_level_(0),
62 num_rec_level_is_zero_(0) { 62 num_rec_level_is_zero_(0),
63 rec_stat_count_(0),
64 play_stat_count_(0) {
63 LOG(INFO) << "AudioDeviceBuffer::ctor"; 65 LOG(INFO) << "AudioDeviceBuffer::ctor";
64 } 66 }
65 67
66 AudioDeviceBuffer::~AudioDeviceBuffer() { 68 AudioDeviceBuffer::~AudioDeviceBuffer() {
67 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 69 RTC_DCHECK(thread_checker_.CalledOnValidThread());
68 LOG(INFO) << "AudioDeviceBuffer::~dtor"; 70 LOG(INFO) << "AudioDeviceBuffer::~dtor";
69 71
70 size_t total_diff_time = 0; 72 size_t total_diff_time = 0;
71 int num_measurements = 0; 73 int num_measurements = 0;
72 LOG(INFO) << "[playout diff time => #measurements]"; 74 LOG(INFO) << "[playout diff time => #measurements]";
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 return 0; 229 return 0;
228 } 230 }
229 231
230 int32_t AudioDeviceBuffer::StopOutputFileRecording() { 232 int32_t AudioDeviceBuffer::StopOutputFileRecording() {
231 LOG(LS_WARNING) << "Not implemented"; 233 LOG(LS_WARNING) << "Not implemented";
232 return 0; 234 return 0;
233 } 235 }
234 236
235 int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audio_buffer, 237 int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audio_buffer,
236 size_t num_samples) { 238 size_t num_samples) {
237 const size_t rec_bytes_per_sample = [&] { 239 const size_t rec_channels = [&] {
238 rtc::CritScope lock(&lock_); 240 rtc::CritScope lock(&lock_);
239 return rec_bytes_per_sample_; 241 return rec_channels_;
240 }(); 242 }();
241 // Copy the complete input buffer to the local buffer. 243 // Copy the complete input buffer to the local buffer.
242 const size_t size_in_bytes = num_samples * rec_bytes_per_sample; 244 const size_t size_in_bytes = num_samples * rec_channels * sizeof(int16_t);
243 const size_t old_size = rec_buffer_.size(); 245 const size_t old_size = rec_buffer_.size();
244 rec_buffer_.SetData(static_cast<const uint8_t*>(audio_buffer), size_in_bytes); 246 rec_buffer_.SetData(static_cast<const uint8_t*>(audio_buffer), size_in_bytes);
245 // Keep track of the size of the recording buffer. Only updated when the 247 // Keep track of the size of the recording buffer. Only updated when the
246 // size changes, which is a rare event. 248 // size changes, which is a rare event.
247 if (old_size != rec_buffer_.size()) { 249 if (old_size != rec_buffer_.size()) {
248 LOG(LS_INFO) << "Size of recording buffer: " << rec_buffer_.size(); 250 LOG(LS_INFO) << "Size of recording buffer: " << rec_buffer_.size();
249 } 251 }
252 // Derive a new level value twice per second.
253 int16_t max_abs = 0;
254 RTC_DCHECK_LT(rec_stat_count_, 50);
255 if (++rec_stat_count_ >= 50) {
256 const size_t size = num_samples * rec_channels;
257 // Returns the largest absolute value in a signed 16-bit vector.
258 max_abs = WebRtcSpl_MaxAbsValueW16(
259 reinterpret_cast<const int16_t*>(rec_buffer_.data()), size);
260 rec_stat_count_ = 0;
261 }
250 // Update some stats but do it on the task queue to ensure that the members 262 // Update some stats but do it on the task queue to ensure that the members
251 // are modified and read on the same thread. 263 // are modified and read on the same thread. Note that |max_abs| will be
264 // zero in most calls and then have no effect of the stats. It is only updated
265 // approximately two times per second and can then change the stats.
252 task_queue_.PostTask(rtc::Bind(&AudioDeviceBuffer::UpdateRecStats, this, 266 task_queue_.PostTask(rtc::Bind(&AudioDeviceBuffer::UpdateRecStats, this,
253 audio_buffer, num_samples)); 267 max_abs, num_samples));
254 return 0; 268 return 0;
255 } 269 }
256 270
257 int32_t AudioDeviceBuffer::DeliverRecordedData() { 271 int32_t AudioDeviceBuffer::DeliverRecordedData() {
258 rtc::CritScope lock(&lock_cb_); 272 rtc::CritScope lock(&lock_cb_);
259 if (!audio_transport_cb_) { 273 if (!audio_transport_cb_) {
260 LOG(LS_WARNING) << "Invalid audio transport"; 274 LOG(LS_WARNING) << "Invalid audio transport";
261 return 0; 275 return 0;
262 } 276 }
263 const size_t rec_bytes_per_sample = [&] { 277 const size_t rec_bytes_per_sample = [&] {
(...skipping 20 matching lines...) Expand all
284 // position/index corresponds to time differences (in milliseconds) between 298 // position/index corresponds to time differences (in milliseconds) between
285 // two successive playout callbacks, and the stored value is the number of 299 // two successive playout callbacks, and the stored value is the number of
286 // times a given time difference was found. 300 // times a given time difference was found.
287 int64_t now_time = rtc::TimeMillis(); 301 int64_t now_time = rtc::TimeMillis();
288 size_t diff_time = rtc::TimeDiff(now_time, last_playout_time_); 302 size_t diff_time = rtc::TimeDiff(now_time, last_playout_time_);
289 // Truncate at 500ms to limit the size of the array. 303 // Truncate at 500ms to limit the size of the array.
290 diff_time = std::min(kMaxDeltaTimeInMs, diff_time); 304 diff_time = std::min(kMaxDeltaTimeInMs, diff_time);
291 last_playout_time_ = now_time; 305 last_playout_time_ = now_time;
292 playout_diff_times_[diff_time]++; 306 playout_diff_times_[diff_time]++;
293 307
294 const size_t play_bytes_per_sample = [&] { 308 const size_t play_channels = [&] {
295 rtc::CritScope lock(&lock_); 309 rtc::CritScope lock(&lock_);
296 return play_bytes_per_sample_; 310 return play_channels_;
297 }(); 311 }();
298 312
299 // The consumer can change the request size on the fly and we therefore 313 // The consumer can change the request size on the fly and we therefore
300 // resize the buffer accordingly. Also takes place at the first call to this 314 // resize the buffer accordingly. Also takes place at the first call to this
301 // method. 315 // method.
316 const size_t play_bytes_per_sample = play_channels * sizeof(int16_t);
302 const size_t size_in_bytes = num_samples * play_bytes_per_sample; 317 const size_t size_in_bytes = num_samples * play_bytes_per_sample;
303 if (play_buffer_.size() != size_in_bytes) { 318 if (play_buffer_.size() != size_in_bytes) {
304 play_buffer_.SetSize(size_in_bytes); 319 play_buffer_.SetSize(size_in_bytes);
305 LOG(LS_INFO) << "Size of playout buffer: " << play_buffer_.size(); 320 LOG(LS_INFO) << "Size of playout buffer: " << play_buffer_.size();
306 } 321 }
307 322
308 rtc::CritScope lock(&lock_cb_); 323 rtc::CritScope lock(&lock_cb_);
309 324
310 // It is currently supported to start playout without a valid audio 325 // It is currently supported to start playout without a valid audio
311 // transport object. Leads to warning and silence. 326 // transport object. Leads to warning and silence.
312 if (!audio_transport_cb_) { 327 if (!audio_transport_cb_) {
313 LOG(LS_WARNING) << "Invalid audio transport"; 328 LOG(LS_WARNING) << "Invalid audio transport";
314 return 0; 329 return 0;
315 } 330 }
316 331
332 // Retrieve new 16-bit PCM audio data using the audio transport instance.
317 int64_t elapsed_time_ms = -1; 333 int64_t elapsed_time_ms = -1;
318 int64_t ntp_time_ms = -1; 334 int64_t ntp_time_ms = -1;
319 size_t num_samples_out(0); 335 size_t num_samples_out(0);
320 uint32_t res = audio_transport_cb_->NeedMorePlayData( 336 uint32_t res = audio_transport_cb_->NeedMorePlayData(
321 num_samples, play_bytes_per_sample_, play_channels_, play_sample_rate_, 337 num_samples, play_bytes_per_sample_, play_channels, play_sample_rate_,
322 play_buffer_.data(), num_samples_out, &elapsed_time_ms, &ntp_time_ms); 338 play_buffer_.data(), num_samples_out, &elapsed_time_ms, &ntp_time_ms);
323 if (res != 0) { 339 if (res != 0) {
324 LOG(LS_ERROR) << "NeedMorePlayData() failed"; 340 LOG(LS_ERROR) << "NeedMorePlayData() failed";
325 } 341 }
326 342
327 // Update some stats but do it on the task queue to ensure that access of 343 // Derive a new level value twice per second.
328 // members is serialized hence avoiding usage of locks. 344 int16_t max_abs = 0;
345 RTC_DCHECK_LT(play_stat_count_, 50);
346 if (++play_stat_count_ >= 50) {
347 const size_t size = num_samples * play_channels;
348 // Returns the largest absolute value in a signed 16-bit vector.
349 max_abs = WebRtcSpl_MaxAbsValueW16(
350 reinterpret_cast<const int16_t*>(play_buffer_.data()), size);
351 play_stat_count_ = 0;
352 }
353 // Update some stats but do it on the task queue to ensure that the members
354 // are modified and read on the same thread. Note that |max_abs| will be
355 // zero in most calls and then have no effect of the stats. It is only updated
356 // approximately two times per second and can then change the stats.
329 task_queue_.PostTask(rtc::Bind(&AudioDeviceBuffer::UpdatePlayStats, this, 357 task_queue_.PostTask(rtc::Bind(&AudioDeviceBuffer::UpdatePlayStats, this,
330 play_buffer_.data(), num_samples_out)); 358 max_abs, num_samples_out));
331 return static_cast<int32_t>(num_samples_out); 359 return static_cast<int32_t>(num_samples_out);
332 } 360 }
333 361
334 int32_t AudioDeviceBuffer::GetPlayoutData(void* audio_buffer) { 362 int32_t AudioDeviceBuffer::GetPlayoutData(void* audio_buffer) {
335 RTC_DCHECK_GT(play_buffer_.size(), 0u); 363 RTC_DCHECK_GT(play_buffer_.size(), 0u);
336 const size_t play_bytes_per_sample = [&] { 364 const size_t play_bytes_per_sample = [&] {
337 rtc::CritScope lock(&lock_); 365 rtc::CritScope lock(&lock_);
338 return play_bytes_per_sample_; 366 return play_bytes_per_sample_;
339 }(); 367 }();
340 memcpy(audio_buffer, play_buffer_.data(), play_buffer_.size()); 368 memcpy(audio_buffer, play_buffer_.data(), play_buffer_.size());
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 442
415 void AudioDeviceBuffer::ResetPlayStats() { 443 void AudioDeviceBuffer::ResetPlayStats() {
416 last_playout_time_ = rtc::TimeMillis(); 444 last_playout_time_ = rtc::TimeMillis();
417 play_callbacks_ = 0; 445 play_callbacks_ = 0;
418 last_play_callbacks_ = 0; 446 last_play_callbacks_ = 0;
419 play_samples_ = 0; 447 play_samples_ = 0;
420 last_play_samples_ = 0; 448 last_play_samples_ = 0;
421 max_play_level_ = 0; 449 max_play_level_ = 0;
422 } 450 }
423 451
424 void AudioDeviceBuffer::UpdateRecStats(const void* audio_buffer, 452 void AudioDeviceBuffer::UpdateRecStats(int16_t max_abs, size_t num_samples) {
425 size_t num_samples) {
426 RTC_DCHECK(task_queue_.IsCurrent()); 453 RTC_DCHECK(task_queue_.IsCurrent());
427 ++rec_callbacks_; 454 ++rec_callbacks_;
428 rec_samples_ += num_samples; 455 rec_samples_ += num_samples;
429 456 if (max_abs > max_rec_level_) {
430 // Find the max absolute value in an audio packet twice per second and update 457 max_rec_level_ = max_abs;
431 // |max_rec_level_| to track the largest value.
432 if (rec_callbacks_ % 50 == 0) {
433 int16_t max_abs = WebRtcSpl_MaxAbsValueW16(
434 static_cast<int16_t*>(const_cast<void*>(audio_buffer)),
435 num_samples * rec_channels_);
436 if (max_abs > max_rec_level_) {
437 max_rec_level_ = max_abs;
438 }
439 } 458 }
440 } 459 }
441 460
442 void AudioDeviceBuffer::UpdatePlayStats(const void* audio_buffer, 461 void AudioDeviceBuffer::UpdatePlayStats(int16_t max_abs, size_t num_samples) {
443 size_t num_samples) {
444 RTC_DCHECK(task_queue_.IsCurrent()); 462 RTC_DCHECK(task_queue_.IsCurrent());
445 ++play_callbacks_; 463 ++play_callbacks_;
446 play_samples_ += num_samples; 464 play_samples_ += num_samples;
447 465 if (max_abs > max_play_level_) {
448 // Find the max absolute value in an audio packet twice per second and update 466 max_play_level_ = max_abs;
449 // |max_play_level_| to track the largest value.
450 if (play_callbacks_ % 50 == 0) {
451 int16_t max_abs = WebRtcSpl_MaxAbsValueW16(
452 static_cast<int16_t*>(const_cast<void*>(audio_buffer)),
453 num_samples * play_channels_);
454 if (max_abs > max_play_level_) {
455 max_play_level_ = max_abs;
456 }
457 } 467 }
458 } 468 }
459 469
460 } // namespace webrtc 470 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_device/audio_device_buffer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698