OLD | NEW |
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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 play_channels_(0), | 46 play_channels_(0), |
47 playing_(false), | 47 playing_(false), |
48 recording_(false), | 48 recording_(false), |
49 current_mic_level_(0), | 49 current_mic_level_(0), |
50 new_mic_level_(0), | 50 new_mic_level_(0), |
51 typing_status_(false), | 51 typing_status_(false), |
52 play_delay_ms_(0), | 52 play_delay_ms_(0), |
53 rec_delay_ms_(0), | 53 rec_delay_ms_(0), |
54 clock_drift_(0), | 54 clock_drift_(0), |
55 num_stat_reports_(0), | 55 num_stat_reports_(0), |
| 56 rec_callbacks_(0), |
| 57 last_rec_callbacks_(0), |
| 58 play_callbacks_(0), |
| 59 last_play_callbacks_(0), |
| 60 rec_samples_(0), |
| 61 last_rec_samples_(0), |
| 62 play_samples_(0), |
| 63 last_play_samples_(0), |
| 64 max_rec_level_(0), |
| 65 max_play_level_(0), |
56 last_timer_task_time_(0), | 66 last_timer_task_time_(0), |
57 rec_stat_count_(0), | 67 rec_stat_count_(0), |
58 play_stat_count_(0), | 68 play_stat_count_(0), |
59 play_start_time_(0), | 69 play_start_time_(0), |
| 70 rec_start_time_(0), |
60 only_silence_recorded_(true), | 71 only_silence_recorded_(true), |
61 log_stats_(false) { | 72 log_stats_(false) { |
62 LOG(INFO) << "AudioDeviceBuffer::ctor"; | 73 LOG(INFO) << "AudioDeviceBuffer::ctor"; |
63 playout_thread_checker_.DetachFromThread(); | 74 playout_thread_checker_.DetachFromThread(); |
64 recording_thread_checker_.DetachFromThread(); | 75 recording_thread_checker_.DetachFromThread(); |
65 } | 76 } |
66 | 77 |
67 AudioDeviceBuffer::~AudioDeviceBuffer() { | 78 AudioDeviceBuffer::~AudioDeviceBuffer() { |
68 RTC_DCHECK_RUN_ON(&main_thread_checker_); | 79 RTC_DCHECK_RUN_ON(&main_thread_checker_); |
69 RTC_DCHECK(!playing_); | 80 RTC_DCHECK(!playing_); |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 // Returns the largest absolute value in a signed 16-bit vector. | 319 // Returns the largest absolute value in a signed 16-bit vector. |
309 max_abs = WebRtcSpl_MaxAbsValueW16(rec_buffer_.data(), rec_buffer_.size()); | 320 max_abs = WebRtcSpl_MaxAbsValueW16(rec_buffer_.data(), rec_buffer_.size()); |
310 rec_stat_count_ = 0; | 321 rec_stat_count_ = 0; |
311 // Set |only_silence_recorded_| to false as soon as at least one detection | 322 // Set |only_silence_recorded_| to false as soon as at least one detection |
312 // of a non-zero audio packet is found. It can only be restored to true | 323 // of a non-zero audio packet is found. It can only be restored to true |
313 // again by restarting the call. | 324 // again by restarting the call. |
314 if (max_abs > 0) { | 325 if (max_abs > 0) { |
315 only_silence_recorded_ = false; | 326 only_silence_recorded_ = false; |
316 } | 327 } |
317 } | 328 } |
318 // Update recording stats which is used as base for periodic logging of the | 329 // Update some stats but do it on the task queue to ensure that the members |
319 // audio input state. | 330 // are modified and read on the same thread. Note that |max_abs| will be |
320 UpdateRecStats(max_abs, samples_per_channel); | 331 // zero in most calls and then have no effect of the stats. It is only updated |
| 332 // approximately two times per second and can then change the stats. |
| 333 task_queue_.PostTask([this, max_abs, samples_per_channel] { |
| 334 UpdateRecStats(max_abs, samples_per_channel); |
| 335 }); |
321 return 0; | 336 return 0; |
322 } | 337 } |
323 | 338 |
324 int32_t AudioDeviceBuffer::DeliverRecordedData() { | 339 int32_t AudioDeviceBuffer::DeliverRecordedData() { |
325 RTC_DCHECK_RUN_ON(&recording_thread_checker_); | 340 RTC_DCHECK_RUN_ON(&recording_thread_checker_); |
326 if (!audio_transport_cb_) { | 341 if (!audio_transport_cb_) { |
327 LOG(LS_WARNING) << "Invalid audio transport"; | 342 LOG(LS_WARNING) << "Invalid audio transport"; |
328 return 0; | 343 return 0; |
329 } | 344 } |
330 const size_t frames = rec_buffer_.size() / rec_channels_; | 345 const size_t frames = rec_buffer_.size() / rec_channels_; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 | 390 |
376 // Derive a new level value twice per second. | 391 // Derive a new level value twice per second. |
377 int16_t max_abs = 0; | 392 int16_t max_abs = 0; |
378 RTC_DCHECK_LT(play_stat_count_, 50); | 393 RTC_DCHECK_LT(play_stat_count_, 50); |
379 if (++play_stat_count_ >= 50) { | 394 if (++play_stat_count_ >= 50) { |
380 // Returns the largest absolute value in a signed 16-bit vector. | 395 // Returns the largest absolute value in a signed 16-bit vector. |
381 max_abs = | 396 max_abs = |
382 WebRtcSpl_MaxAbsValueW16(play_buffer_.data(), play_buffer_.size()); | 397 WebRtcSpl_MaxAbsValueW16(play_buffer_.data(), play_buffer_.size()); |
383 play_stat_count_ = 0; | 398 play_stat_count_ = 0; |
384 } | 399 } |
385 // Update playout stats which is used as base for periodic logging of the | 400 // Update some stats but do it on the task queue to ensure that the members |
386 // audio output state. | 401 // are modified and read on the same thread. Note that |max_abs| will be |
387 UpdatePlayStats(max_abs, num_samples_out); | 402 // zero in most calls and then have no effect of the stats. It is only updated |
| 403 // approximately two times per second and can then change the stats. |
| 404 task_queue_.PostTask([this, max_abs, num_samples_out] { |
| 405 UpdatePlayStats(max_abs, num_samples_out); |
| 406 }); |
388 return static_cast<int32_t>(num_samples_out); | 407 return static_cast<int32_t>(num_samples_out); |
389 } | 408 } |
390 | 409 |
391 int32_t AudioDeviceBuffer::GetPlayoutData(void* audio_buffer) { | 410 int32_t AudioDeviceBuffer::GetPlayoutData(void* audio_buffer) { |
392 RTC_DCHECK_RUN_ON(&playout_thread_checker_); | 411 RTC_DCHECK_RUN_ON(&playout_thread_checker_); |
393 RTC_DCHECK_GT(play_buffer_.size(), 0); | 412 RTC_DCHECK_GT(play_buffer_.size(), 0); |
394 const size_t bytes_per_sample = sizeof(int16_t); | 413 const size_t bytes_per_sample = sizeof(int16_t); |
395 memcpy(audio_buffer, play_buffer_.data(), | 414 memcpy(audio_buffer, play_buffer_.data(), |
396 play_buffer_.size() * bytes_per_sample); | 415 play_buffer_.size() * bytes_per_sample); |
397 // Return samples per channel or number of frames. | 416 // Return samples per channel or number of frames. |
(...skipping 29 matching lines...) Expand all Loading... |
427 | 446 |
428 // Avoid adding more logs since we are in STOP mode. | 447 // Avoid adding more logs since we are in STOP mode. |
429 if (!log_stats_) { | 448 if (!log_stats_) { |
430 return; | 449 return; |
431 } | 450 } |
432 | 451 |
433 int64_t next_callback_time = now_time + kTimerIntervalInMilliseconds; | 452 int64_t next_callback_time = now_time + kTimerIntervalInMilliseconds; |
434 int64_t time_since_last = rtc::TimeDiff(now_time, last_timer_task_time_); | 453 int64_t time_since_last = rtc::TimeDiff(now_time, last_timer_task_time_); |
435 last_timer_task_time_ = now_time; | 454 last_timer_task_time_ = now_time; |
436 | 455 |
437 Stats stats; | |
438 { | |
439 rtc::CritScope cs(&lock_); | |
440 stats = stats_; | |
441 stats_.max_rec_level = 0; | |
442 stats_.max_play_level = 0; | |
443 } | |
444 | |
445 // Log the latest statistics but skip the first round just after state was | 456 // Log the latest statistics but skip the first round just after state was |
446 // set to LOG_START. Hence, first printed log will be after ~10 seconds. | 457 // set to LOG_START. Hence, first printed log will be after ~10 seconds. |
447 if (++num_stat_reports_ > 1 && time_since_last > 0) { | 458 if (++num_stat_reports_ > 1 && time_since_last > 0) { |
448 uint32_t diff_samples = stats.rec_samples - last_stats_.rec_samples; | 459 uint32_t diff_samples = rec_samples_ - last_rec_samples_; |
449 float rate = diff_samples / (static_cast<float>(time_since_last) / 1000.0); | 460 float rate = diff_samples / (static_cast<float>(time_since_last) / 1000.0); |
450 LOG(INFO) << "[REC : " << time_since_last << "msec, " | 461 LOG(INFO) << "[REC : " << time_since_last << "msec, " |
451 << rec_sample_rate_ / 1000 << "kHz] callbacks: " | 462 << rec_sample_rate_ / 1000 |
452 << stats.rec_callbacks - last_stats_.rec_callbacks << ", " | 463 << "kHz] callbacks: " << rec_callbacks_ - last_rec_callbacks_ |
| 464 << ", " |
453 << "samples: " << diff_samples << ", " | 465 << "samples: " << diff_samples << ", " |
454 << "rate: " << static_cast<int>(rate + 0.5) << ", " | 466 << "rate: " << static_cast<int>(rate + 0.5) << ", " |
455 << "level: " << stats.max_rec_level; | 467 << "level: " << max_rec_level_; |
456 | 468 |
457 diff_samples = stats.play_samples - last_stats_.play_samples; | 469 diff_samples = play_samples_ - last_play_samples_; |
458 rate = diff_samples / (static_cast<float>(time_since_last) / 1000.0); | 470 rate = diff_samples / (static_cast<float>(time_since_last) / 1000.0); |
459 LOG(INFO) << "[PLAY: " << time_since_last << "msec, " | 471 LOG(INFO) << "[PLAY: " << time_since_last << "msec, " |
460 << play_sample_rate_ / 1000 << "kHz] callbacks: " | 472 << play_sample_rate_ / 1000 |
461 << stats.play_callbacks - last_stats_.play_callbacks << ", " | 473 << "kHz] callbacks: " << play_callbacks_ - last_play_callbacks_ |
| 474 << ", " |
462 << "samples: " << diff_samples << ", " | 475 << "samples: " << diff_samples << ", " |
463 << "rate: " << static_cast<int>(rate + 0.5) << ", " | 476 << "rate: " << static_cast<int>(rate + 0.5) << ", " |
464 << "level: " << stats.max_play_level; | 477 << "level: " << max_play_level_; |
465 last_stats_ = stats; | |
466 } | 478 } |
467 | 479 |
| 480 last_rec_callbacks_ = rec_callbacks_; |
| 481 last_play_callbacks_ = play_callbacks_; |
| 482 last_rec_samples_ = rec_samples_; |
| 483 last_play_samples_ = play_samples_; |
| 484 max_rec_level_ = 0; |
| 485 max_play_level_ = 0; |
| 486 |
468 int64_t time_to_wait_ms = next_callback_time - rtc::TimeMillis(); | 487 int64_t time_to_wait_ms = next_callback_time - rtc::TimeMillis(); |
469 RTC_DCHECK_GT(time_to_wait_ms, 0) << "Invalid timer interval"; | 488 RTC_DCHECK_GT(time_to_wait_ms, 0) << "Invalid timer interval"; |
470 | 489 |
471 // Keep posting new (delayed) tasks until state is changed to kLogStop. | 490 // Keep posting new (delayed) tasks until state is changed to kLogStop. |
472 task_queue_.PostDelayedTask(rtc::Bind(&AudioDeviceBuffer::LogStats, this, | 491 task_queue_.PostDelayedTask(rtc::Bind(&AudioDeviceBuffer::LogStats, this, |
473 AudioDeviceBuffer::LOG_ACTIVE), | 492 AudioDeviceBuffer::LOG_ACTIVE), |
474 time_to_wait_ms); | 493 time_to_wait_ms); |
475 } | 494 } |
476 | 495 |
477 void AudioDeviceBuffer::ResetRecStats() { | 496 void AudioDeviceBuffer::ResetRecStats() { |
478 RTC_DCHECK_RUN_ON(&task_queue_); | 497 RTC_DCHECK_RUN_ON(&task_queue_); |
479 last_stats_.ResetRecStats(); | 498 rec_callbacks_ = 0; |
480 rtc::CritScope cs(&lock_); | 499 last_rec_callbacks_ = 0; |
481 stats_.ResetRecStats(); | 500 rec_samples_ = 0; |
| 501 last_rec_samples_ = 0; |
| 502 max_rec_level_ = 0; |
482 } | 503 } |
483 | 504 |
484 void AudioDeviceBuffer::ResetPlayStats() { | 505 void AudioDeviceBuffer::ResetPlayStats() { |
485 RTC_DCHECK_RUN_ON(&task_queue_); | 506 RTC_DCHECK_RUN_ON(&task_queue_); |
486 last_stats_.ResetPlayStats(); | 507 play_callbacks_ = 0; |
487 rtc::CritScope cs(&lock_); | 508 last_play_callbacks_ = 0; |
488 stats_.ResetPlayStats(); | 509 play_samples_ = 0; |
| 510 last_play_samples_ = 0; |
| 511 max_play_level_ = 0; |
489 } | 512 } |
490 | 513 |
491 void AudioDeviceBuffer::UpdateRecStats(int16_t max_abs, | 514 void AudioDeviceBuffer::UpdateRecStats(int16_t max_abs, |
492 size_t samples_per_channel) { | 515 size_t samples_per_channel) { |
493 RTC_DCHECK_RUN_ON(&recording_thread_checker_); | 516 RTC_DCHECK_RUN_ON(&task_queue_); |
494 rtc::CritScope cs(&lock_); | 517 ++rec_callbacks_; |
495 ++stats_.rec_callbacks; | 518 rec_samples_ += samples_per_channel; |
496 stats_.rec_samples += samples_per_channel; | 519 if (max_abs > max_rec_level_) { |
497 if (max_abs > stats_.max_rec_level) { | 520 max_rec_level_ = max_abs; |
498 stats_.max_rec_level = max_abs; | |
499 } | 521 } |
500 } | 522 } |
501 | 523 |
502 void AudioDeviceBuffer::UpdatePlayStats(int16_t max_abs, | 524 void AudioDeviceBuffer::UpdatePlayStats(int16_t max_abs, |
503 size_t samples_per_channel) { | 525 size_t samples_per_channel) { |
504 RTC_DCHECK_RUN_ON(&playout_thread_checker_); | 526 RTC_DCHECK_RUN_ON(&task_queue_); |
505 rtc::CritScope cs(&lock_); | 527 ++play_callbacks_; |
506 ++stats_.play_callbacks; | 528 play_samples_ += samples_per_channel; |
507 stats_.play_samples += samples_per_channel; | 529 if (max_abs > max_play_level_) { |
508 if (max_abs > stats_.max_play_level) { | 530 max_play_level_ = max_abs; |
509 stats_.max_play_level = max_abs; | |
510 } | 531 } |
511 } | 532 } |
512 | 533 |
513 } // namespace webrtc | 534 } // namespace webrtc |
OLD | NEW |