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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 (using max(abs())) twice per second. | |
253 int16_t max_abs = 0; | |
254 if (++rec_stat_count_ == 50) { | |
kwiberg-webrtc
2016/10/20 17:02:59
Either DCHECK that the value isn't more than 50, o
henrika_webrtc
2016/10/21 08:40:22
Sure thing but should it really be needed?
kwiberg-webrtc
2016/10/21 09:04:43
Well, no. DCHECKs are, by design, never needed, si
| |
255 const size_t size = num_samples * rec_channels; | |
256 max_abs = WebRtcSpl_MaxAbsValueW16( | |
257 static_cast<int16_t*>(const_cast<void*>(audio_buffer)), size); | |
kwiberg-webrtc
2016/10/20 17:02:59
You shouldn't need to cast away the constness. Web
| |
258 rec_stat_count_ = 0; | |
259 } | |
250 // Update some stats but do it on the task queue to ensure that the members | 260 // Update some stats but do it on the task queue to ensure that the members |
251 // are modified and read on the same thread. | 261 // are modified and read on the same thread. Note that |max_abs| will only be |
262 // non-zero two times per second approximately. | |
kwiberg-webrtc
2016/10/20 17:02:59
Don't you mean rec_stat_count_? Or that max_abs wi
henrika_webrtc
2016/10/21 08:40:22
I mean max_abs. Let me elaborate.
| |
252 task_queue_.PostTask(rtc::Bind(&AudioDeviceBuffer::UpdateRecStats, this, | 263 task_queue_.PostTask(rtc::Bind(&AudioDeviceBuffer::UpdateRecStats, this, |
253 audio_buffer, num_samples)); | 264 max_abs, num_samples)); |
254 return 0; | 265 return 0; |
255 } | 266 } |
256 | 267 |
257 int32_t AudioDeviceBuffer::DeliverRecordedData() { | 268 int32_t AudioDeviceBuffer::DeliverRecordedData() { |
258 rtc::CritScope lock(&lock_cb_); | 269 rtc::CritScope lock(&lock_cb_); |
259 if (!audio_transport_cb_) { | 270 if (!audio_transport_cb_) { |
260 LOG(LS_WARNING) << "Invalid audio transport"; | 271 LOG(LS_WARNING) << "Invalid audio transport"; |
261 return 0; | 272 return 0; |
262 } | 273 } |
263 const size_t rec_bytes_per_sample = [&] { | 274 const size_t rec_bytes_per_sample = [&] { |
(...skipping 20 matching lines...) Expand all Loading... | |
284 // position/index corresponds to time differences (in milliseconds) between | 295 // position/index corresponds to time differences (in milliseconds) between |
285 // two successive playout callbacks, and the stored value is the number of | 296 // two successive playout callbacks, and the stored value is the number of |
286 // times a given time difference was found. | 297 // times a given time difference was found. |
287 int64_t now_time = rtc::TimeMillis(); | 298 int64_t now_time = rtc::TimeMillis(); |
288 size_t diff_time = rtc::TimeDiff(now_time, last_playout_time_); | 299 size_t diff_time = rtc::TimeDiff(now_time, last_playout_time_); |
289 // Truncate at 500ms to limit the size of the array. | 300 // Truncate at 500ms to limit the size of the array. |
290 diff_time = std::min(kMaxDeltaTimeInMs, diff_time); | 301 diff_time = std::min(kMaxDeltaTimeInMs, diff_time); |
291 last_playout_time_ = now_time; | 302 last_playout_time_ = now_time; |
292 playout_diff_times_[diff_time]++; | 303 playout_diff_times_[diff_time]++; |
293 | 304 |
294 const size_t play_bytes_per_sample = [&] { | 305 const size_t play_channels = [&] { |
295 rtc::CritScope lock(&lock_); | 306 rtc::CritScope lock(&lock_); |
296 return play_bytes_per_sample_; | 307 return play_channels_; |
297 }(); | 308 }(); |
298 | 309 |
299 // The consumer can change the request size on the fly and we therefore | 310 // 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 | 311 // resize the buffer accordingly. Also takes place at the first call to this |
301 // method. | 312 // method. |
313 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; | 314 const size_t size_in_bytes = num_samples * play_bytes_per_sample; |
303 if (play_buffer_.size() != size_in_bytes) { | 315 if (play_buffer_.size() != size_in_bytes) { |
304 play_buffer_.SetSize(size_in_bytes); | 316 play_buffer_.SetSize(size_in_bytes); |
305 LOG(LS_INFO) << "Size of playout buffer: " << play_buffer_.size(); | 317 LOG(LS_INFO) << "Size of playout buffer: " << play_buffer_.size(); |
306 } | 318 } |
307 | 319 |
308 rtc::CritScope lock(&lock_cb_); | 320 rtc::CritScope lock(&lock_cb_); |
309 | 321 |
310 // It is currently supported to start playout without a valid audio | 322 // It is currently supported to start playout without a valid audio |
311 // transport object. Leads to warning and silence. | 323 // transport object. Leads to warning and silence. |
312 if (!audio_transport_cb_) { | 324 if (!audio_transport_cb_) { |
313 LOG(LS_WARNING) << "Invalid audio transport"; | 325 LOG(LS_WARNING) << "Invalid audio transport"; |
314 return 0; | 326 return 0; |
315 } | 327 } |
316 | 328 |
329 // Retrieve new 16-bit PCM audio data using the audio transport instance. | |
317 int64_t elapsed_time_ms = -1; | 330 int64_t elapsed_time_ms = -1; |
318 int64_t ntp_time_ms = -1; | 331 int64_t ntp_time_ms = -1; |
319 size_t num_samples_out(0); | 332 size_t num_samples_out(0); |
320 uint32_t res = audio_transport_cb_->NeedMorePlayData( | 333 uint32_t res = audio_transport_cb_->NeedMorePlayData( |
321 num_samples, play_bytes_per_sample_, play_channels_, play_sample_rate_, | 334 num_samples, play_bytes_per_sample_, play_channels, play_sample_rate_, |
322 play_buffer_.data(), num_samples_out, &elapsed_time_ms, &ntp_time_ms); | 335 play_buffer_.data(), num_samples_out, &elapsed_time_ms, &ntp_time_ms); |
323 if (res != 0) { | 336 if (res != 0) { |
324 LOG(LS_ERROR) << "NeedMorePlayData() failed"; | 337 LOG(LS_ERROR) << "NeedMorePlayData() failed"; |
325 } | 338 } |
326 | 339 |
327 // Update some stats but do it on the task queue to ensure that access of | 340 // Derive a new level value (using max(abs())) twice per second. |
328 // members is serialized hence avoiding usage of locks. | 341 int16_t max_abs = 0; |
342 if (++play_stat_count_ == 50) { | |
kwiberg-webrtc
2016/10/20 17:02:59
DCHECK and/or >=
henrika_webrtc
2016/10/21 08:40:22
Done.
| |
343 const size_t size = num_samples * play_channels; | |
344 max_abs = WebRtcSpl_MaxAbsValueW16( | |
345 reinterpret_cast<int16_t*>(play_buffer_.data()), size); | |
kwiberg-webrtc
2016/10/20 17:02:59
You use static_cast in the other loop. Please be c
henrika_webrtc
2016/10/21 08:40:22
Will fix.
| |
346 play_stat_count_ = 0; | |
347 } | |
348 // Update some stats but do it on the task queue to ensure that the members | |
349 // are modified and read on the same thread. Note that |max_abs| will only be | |
350 // non-zero two times per second approximately. | |
kwiberg-webrtc
2016/10/20 17:02:59
Comment wrong here too?
henrika_webrtc
2016/10/21 08:40:22
Actually no but let me explain better.
| |
329 task_queue_.PostTask(rtc::Bind(&AudioDeviceBuffer::UpdatePlayStats, this, | 351 task_queue_.PostTask(rtc::Bind(&AudioDeviceBuffer::UpdatePlayStats, this, |
330 play_buffer_.data(), num_samples_out)); | 352 max_abs, num_samples_out)); |
331 return static_cast<int32_t>(num_samples_out); | 353 return static_cast<int32_t>(num_samples_out); |
332 } | 354 } |
333 | 355 |
334 int32_t AudioDeviceBuffer::GetPlayoutData(void* audio_buffer) { | 356 int32_t AudioDeviceBuffer::GetPlayoutData(void* audio_buffer) { |
335 RTC_DCHECK_GT(play_buffer_.size(), 0u); | 357 RTC_DCHECK_GT(play_buffer_.size(), 0u); |
336 const size_t play_bytes_per_sample = [&] { | 358 const size_t play_bytes_per_sample = [&] { |
337 rtc::CritScope lock(&lock_); | 359 rtc::CritScope lock(&lock_); |
338 return play_bytes_per_sample_; | 360 return play_bytes_per_sample_; |
339 }(); | 361 }(); |
340 memcpy(audio_buffer, play_buffer_.data(), play_buffer_.size()); | 362 memcpy(audio_buffer, play_buffer_.data(), play_buffer_.size()); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
414 | 436 |
415 void AudioDeviceBuffer::ResetPlayStats() { | 437 void AudioDeviceBuffer::ResetPlayStats() { |
416 last_playout_time_ = rtc::TimeMillis(); | 438 last_playout_time_ = rtc::TimeMillis(); |
417 play_callbacks_ = 0; | 439 play_callbacks_ = 0; |
418 last_play_callbacks_ = 0; | 440 last_play_callbacks_ = 0; |
419 play_samples_ = 0; | 441 play_samples_ = 0; |
420 last_play_samples_ = 0; | 442 last_play_samples_ = 0; |
421 max_play_level_ = 0; | 443 max_play_level_ = 0; |
422 } | 444 } |
423 | 445 |
424 void AudioDeviceBuffer::UpdateRecStats(const void* audio_buffer, | 446 void AudioDeviceBuffer::UpdateRecStats(int16_t max_abs, size_t num_samples) { |
425 size_t num_samples) { | |
426 RTC_DCHECK(task_queue_.IsCurrent()); | 447 RTC_DCHECK(task_queue_.IsCurrent()); |
427 ++rec_callbacks_; | 448 ++rec_callbacks_; |
428 rec_samples_ += num_samples; | 449 rec_samples_ += num_samples; |
429 | 450 if (max_abs > max_rec_level_) { |
430 // Find the max absolute value in an audio packet twice per second and update | 451 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 } | 452 } |
440 } | 453 } |
441 | 454 |
442 void AudioDeviceBuffer::UpdatePlayStats(const void* audio_buffer, | 455 void AudioDeviceBuffer::UpdatePlayStats(int16_t max_abs, size_t num_samples) { |
443 size_t num_samples) { | |
444 RTC_DCHECK(task_queue_.IsCurrent()); | 456 RTC_DCHECK(task_queue_.IsCurrent()); |
445 ++play_callbacks_; | 457 ++play_callbacks_; |
446 play_samples_ += num_samples; | 458 play_samples_ += num_samples; |
447 | 459 if (max_abs > max_play_level_) { |
448 // Find the max absolute value in an audio packet twice per second and update | 460 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 } | 461 } |
458 } | 462 } |
459 | 463 |
460 } // namespace webrtc | 464 } // namespace webrtc |
OLD | NEW |