OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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 "webrtc/modules/audio_coding/acm2/acm_receiver.h" | 11 #include "webrtc/modules/audio_coding/acm2/acm_receiver.h" |
12 | 12 |
13 #include <stdlib.h> // malloc | 13 #include <stdlib.h> // malloc |
14 | 14 |
15 #include <algorithm> // sort | 15 #include <algorithm> // sort |
16 #include <vector> | 16 #include <vector> |
17 | 17 |
18 #include "webrtc/base/checks.h" | 18 #include "webrtc/base/checks.h" |
19 #include "webrtc/base/format_macros.h" | 19 #include "webrtc/base/format_macros.h" |
20 #include "webrtc/base/logging.h" | 20 #include "webrtc/base/logging.h" |
21 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
y.h" | 21 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
y.h" |
22 #include "webrtc/common_types.h" | 22 #include "webrtc/common_types.h" |
23 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" | 23 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" |
24 #include "webrtc/modules/audio_coding/acm2/acm_resampler.h" | 24 #include "webrtc/modules/audio_coding/acm2/acm_resampler.h" |
25 #include "webrtc/modules/audio_coding/acm2/call_statistics.h" | 25 #include "webrtc/modules/audio_coding/acm2/call_statistics.h" |
26 #include "webrtc/modules/audio_coding/neteq/include/neteq.h" | 26 #include "webrtc/modules/audio_coding/neteq/include/neteq.h" |
27 #include "webrtc/system_wrappers/include/clock.h" | 27 #include "webrtc/system_wrappers/include/clock.h" |
28 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | |
29 #include "webrtc/system_wrappers/include/tick_util.h" | 28 #include "webrtc/system_wrappers/include/tick_util.h" |
30 #include "webrtc/system_wrappers/include/trace.h" | 29 #include "webrtc/system_wrappers/include/trace.h" |
31 | 30 |
32 namespace webrtc { | 31 namespace webrtc { |
33 | 32 |
34 namespace acm2 { | 33 namespace acm2 { |
35 | 34 |
36 namespace { | 35 namespace { |
37 | 36 |
38 // |vad_activity_| field of |audio_frame| is set to |previous_audio_activity_| | 37 // |vad_activity_| field of |audio_frame| is set to |previous_audio_activity_| |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 auto i = RentACodec::CodecIdFromIndex(codec_id); | 111 auto i = RentACodec::CodecIdFromIndex(codec_id); |
113 return (i && (*i == RentACodec::CodecId::kCNNB || | 112 return (i && (*i == RentACodec::CodecId::kCNNB || |
114 *i == RentACodec::CodecId::kCNWB || | 113 *i == RentACodec::CodecId::kCNWB || |
115 *i == RentACodec::CodecId::kCNSWB || | 114 *i == RentACodec::CodecId::kCNSWB || |
116 *i == RentACodec::CodecId::kCNFB)); | 115 *i == RentACodec::CodecId::kCNFB)); |
117 } | 116 } |
118 | 117 |
119 } // namespace | 118 } // namespace |
120 | 119 |
121 AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config) | 120 AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config) |
122 : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), | 121 : id_(config.id), |
123 id_(config.id), | |
124 last_audio_decoder_(nullptr), | 122 last_audio_decoder_(nullptr), |
125 previous_audio_activity_(AudioFrame::kVadPassive), | 123 previous_audio_activity_(AudioFrame::kVadPassive), |
126 audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), | 124 audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), |
127 last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), | 125 last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), |
128 neteq_(NetEq::Create(config.neteq_config)), | 126 neteq_(NetEq::Create(config.neteq_config)), |
129 vad_enabled_(config.neteq_config.enable_post_decode_vad), | 127 vad_enabled_(config.neteq_config.enable_post_decode_vad), |
130 clock_(config.clock), | 128 clock_(config.clock), |
131 resampled_last_output_frame_(true) { | 129 resampled_last_output_frame_(true) { |
132 assert(clock_); | 130 assert(clock_); |
133 memset(audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples); | 131 memset(audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples); |
(...skipping 16 matching lines...) Expand all Loading... |
150 return 0; | 148 return 0; |
151 LOG(LERROR) << "AcmReceiver::SetExtraDelay " << delay_ms; | 149 LOG(LERROR) << "AcmReceiver::SetExtraDelay " << delay_ms; |
152 return -1; | 150 return -1; |
153 } | 151 } |
154 | 152 |
155 int AcmReceiver::LeastRequiredDelayMs() const { | 153 int AcmReceiver::LeastRequiredDelayMs() const { |
156 return neteq_->LeastRequiredDelayMs(); | 154 return neteq_->LeastRequiredDelayMs(); |
157 } | 155 } |
158 | 156 |
159 rtc::Optional<int> AcmReceiver::last_packet_sample_rate_hz() const { | 157 rtc::Optional<int> AcmReceiver::last_packet_sample_rate_hz() const { |
160 CriticalSectionScoped lock(crit_sect_.get()); | 158 rtc::CritScope lock(&crit_sect_); |
161 return last_packet_sample_rate_hz_; | 159 return last_packet_sample_rate_hz_; |
162 } | 160 } |
163 | 161 |
164 int AcmReceiver::last_output_sample_rate_hz() const { | 162 int AcmReceiver::last_output_sample_rate_hz() const { |
165 return neteq_->last_output_sample_rate_hz(); | 163 return neteq_->last_output_sample_rate_hz(); |
166 } | 164 } |
167 | 165 |
168 int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header, | 166 int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header, |
169 rtc::ArrayView<const uint8_t> incoming_payload) { | 167 rtc::ArrayView<const uint8_t> incoming_payload) { |
170 uint32_t receive_timestamp = 0; | 168 uint32_t receive_timestamp = 0; |
171 const RTPHeader* header = &rtp_header.header; // Just a shorthand. | 169 const RTPHeader* header = &rtp_header.header; // Just a shorthand. |
172 | 170 |
173 { | 171 { |
174 CriticalSectionScoped lock(crit_sect_.get()); | 172 rtc::CritScope lock(&crit_sect_); |
175 | 173 |
176 const Decoder* decoder = RtpHeaderToDecoder(*header, incoming_payload[0]); | 174 const Decoder* decoder = RtpHeaderToDecoder(*header, incoming_payload[0]); |
177 if (!decoder) { | 175 if (!decoder) { |
178 LOG_F(LS_ERROR) << "Payload-type " | 176 LOG_F(LS_ERROR) << "Payload-type " |
179 << static_cast<int>(header->payloadType) | 177 << static_cast<int>(header->payloadType) |
180 << " is not registered."; | 178 << " is not registered."; |
181 return -1; | 179 return -1; |
182 } | 180 } |
183 const int sample_rate_hz = [&decoder] { | 181 const int sample_rate_hz = [&decoder] { |
184 const auto ci = RentACodec::CodecIdFromIndex(decoder->acm_codec_id); | 182 const auto ci = RentACodec::CodecIdFromIndex(decoder->acm_codec_id); |
(...skipping 24 matching lines...) Expand all Loading... |
209 } | 207 } |
210 return 0; | 208 return 0; |
211 } | 209 } |
212 | 210 |
213 int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) { | 211 int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) { |
214 enum NetEqOutputType type; | 212 enum NetEqOutputType type; |
215 size_t samples_per_channel; | 213 size_t samples_per_channel; |
216 size_t num_channels; | 214 size_t num_channels; |
217 | 215 |
218 // Accessing members, take the lock. | 216 // Accessing members, take the lock. |
219 CriticalSectionScoped lock(crit_sect_.get()); | 217 rtc::CritScope lock(&crit_sect_); |
220 | 218 |
221 // Always write the output to |audio_buffer_| first. | 219 // Always write the output to |audio_buffer_| first. |
222 if (neteq_->GetAudio(AudioFrame::kMaxDataSizeSamples, | 220 if (neteq_->GetAudio(AudioFrame::kMaxDataSizeSamples, |
223 audio_buffer_.get(), | 221 audio_buffer_.get(), |
224 &samples_per_channel, | 222 &samples_per_channel, |
225 &num_channels, | 223 &num_channels, |
226 &type) != NetEq::kOK) { | 224 &type) != NetEq::kOK) { |
227 LOG(LERROR) << "AcmReceiver::GetAudio - NetEq Failed."; | 225 LOG(LERROR) << "AcmReceiver::GetAudio - NetEq Failed."; |
228 return -1; | 226 return -1; |
229 } | 227 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 return NetEqDecoder::kDecoderArbitrary; // External decoder. | 308 return NetEqDecoder::kDecoderArbitrary; // External decoder. |
311 const rtc::Optional<RentACodec::CodecId> cid = | 309 const rtc::Optional<RentACodec::CodecId> cid = |
312 RentACodec::CodecIdFromIndex(acm_codec_id); | 310 RentACodec::CodecIdFromIndex(acm_codec_id); |
313 RTC_DCHECK(cid) << "Invalid codec index: " << acm_codec_id; | 311 RTC_DCHECK(cid) << "Invalid codec index: " << acm_codec_id; |
314 const rtc::Optional<NetEqDecoder> ned = | 312 const rtc::Optional<NetEqDecoder> ned = |
315 RentACodec::NetEqDecoderFromCodecId(*cid, channels); | 313 RentACodec::NetEqDecoderFromCodecId(*cid, channels); |
316 RTC_DCHECK(ned) << "Invalid codec ID: " << static_cast<int>(*cid); | 314 RTC_DCHECK(ned) << "Invalid codec ID: " << static_cast<int>(*cid); |
317 return *ned; | 315 return *ned; |
318 }(); | 316 }(); |
319 | 317 |
320 CriticalSectionScoped lock(crit_sect_.get()); | 318 rtc::CritScope lock(&crit_sect_); |
321 | 319 |
322 // The corresponding NetEq decoder ID. | 320 // The corresponding NetEq decoder ID. |
323 // If this codec has been registered before. | 321 // If this codec has been registered before. |
324 auto it = decoders_.find(payload_type); | 322 auto it = decoders_.find(payload_type); |
325 if (it != decoders_.end()) { | 323 if (it != decoders_.end()) { |
326 const Decoder& decoder = it->second; | 324 const Decoder& decoder = it->second; |
327 if (acm_codec_id != -1 && decoder.acm_codec_id == acm_codec_id && | 325 if (acm_codec_id != -1 && decoder.acm_codec_id == acm_codec_id && |
328 decoder.channels == channels && | 326 decoder.channels == channels && |
329 decoder.sample_rate_hz == sample_rate_hz) { | 327 decoder.sample_rate_hz == sample_rate_hz) { |
330 // Re-registering the same codec. Do nothing and return. | 328 // Re-registering the same codec. Do nothing and return. |
(...skipping 28 matching lines...) Expand all Loading... |
359 decoder.acm_codec_id = acm_codec_id; | 357 decoder.acm_codec_id = acm_codec_id; |
360 decoder.payload_type = payload_type; | 358 decoder.payload_type = payload_type; |
361 decoder.channels = channels; | 359 decoder.channels = channels; |
362 decoder.sample_rate_hz = sample_rate_hz; | 360 decoder.sample_rate_hz = sample_rate_hz; |
363 decoders_[payload_type] = decoder; | 361 decoders_[payload_type] = decoder; |
364 return 0; | 362 return 0; |
365 } | 363 } |
366 | 364 |
367 void AcmReceiver::EnableVad() { | 365 void AcmReceiver::EnableVad() { |
368 neteq_->EnableVad(); | 366 neteq_->EnableVad(); |
369 CriticalSectionScoped lock(crit_sect_.get()); | 367 rtc::CritScope lock(&crit_sect_); |
370 vad_enabled_ = true; | 368 vad_enabled_ = true; |
371 } | 369 } |
372 | 370 |
373 void AcmReceiver::DisableVad() { | 371 void AcmReceiver::DisableVad() { |
374 neteq_->DisableVad(); | 372 neteq_->DisableVad(); |
375 CriticalSectionScoped lock(crit_sect_.get()); | 373 rtc::CritScope lock(&crit_sect_); |
376 vad_enabled_ = false; | 374 vad_enabled_ = false; |
377 } | 375 } |
378 | 376 |
379 void AcmReceiver::FlushBuffers() { | 377 void AcmReceiver::FlushBuffers() { |
380 neteq_->FlushBuffers(); | 378 neteq_->FlushBuffers(); |
381 } | 379 } |
382 | 380 |
383 // If failed in removing one of the codecs, this method continues to remove as | 381 // If failed in removing one of the codecs, this method continues to remove as |
384 // many as it can. | 382 // many as it can. |
385 int AcmReceiver::RemoveAllCodecs() { | 383 int AcmReceiver::RemoveAllCodecs() { |
386 int ret_val = 0; | 384 int ret_val = 0; |
387 CriticalSectionScoped lock(crit_sect_.get()); | 385 rtc::CritScope lock(&crit_sect_); |
388 for (auto it = decoders_.begin(); it != decoders_.end(); ) { | 386 for (auto it = decoders_.begin(); it != decoders_.end(); ) { |
389 auto cur = it; | 387 auto cur = it; |
390 ++it; // it will be valid even if we erase cur | 388 ++it; // it will be valid even if we erase cur |
391 if (neteq_->RemovePayloadType(cur->second.payload_type) == 0) { | 389 if (neteq_->RemovePayloadType(cur->second.payload_type) == 0) { |
392 decoders_.erase(cur); | 390 decoders_.erase(cur); |
393 } else { | 391 } else { |
394 LOG_F(LS_ERROR) << "Cannot remove payload " | 392 LOG_F(LS_ERROR) << "Cannot remove payload " |
395 << static_cast<int>(cur->second.payload_type); | 393 << static_cast<int>(cur->second.payload_type); |
396 ret_val = -1; | 394 ret_val = -1; |
397 } | 395 } |
398 } | 396 } |
399 | 397 |
400 // No codec is registered, invalidate last audio decoder. | 398 // No codec is registered, invalidate last audio decoder. |
401 last_audio_decoder_ = nullptr; | 399 last_audio_decoder_ = nullptr; |
402 last_packet_sample_rate_hz_ = rtc::Optional<int>(); | 400 last_packet_sample_rate_hz_ = rtc::Optional<int>(); |
403 return ret_val; | 401 return ret_val; |
404 } | 402 } |
405 | 403 |
406 int AcmReceiver::RemoveCodec(uint8_t payload_type) { | 404 int AcmReceiver::RemoveCodec(uint8_t payload_type) { |
407 CriticalSectionScoped lock(crit_sect_.get()); | 405 rtc::CritScope lock(&crit_sect_); |
408 auto it = decoders_.find(payload_type); | 406 auto it = decoders_.find(payload_type); |
409 if (it == decoders_.end()) { // Such a payload-type is not registered. | 407 if (it == decoders_.end()) { // Such a payload-type is not registered. |
410 return 0; | 408 return 0; |
411 } | 409 } |
412 if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) { | 410 if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) { |
413 LOG(LERROR) << "AcmReceiver::RemoveCodec" << static_cast<int>(payload_type); | 411 LOG(LERROR) << "AcmReceiver::RemoveCodec" << static_cast<int>(payload_type); |
414 return -1; | 412 return -1; |
415 } | 413 } |
416 if (last_audio_decoder_ == &it->second) { | 414 if (last_audio_decoder_ == &it->second) { |
417 last_audio_decoder_ = nullptr; | 415 last_audio_decoder_ = nullptr; |
418 last_packet_sample_rate_hz_ = rtc::Optional<int>(); | 416 last_packet_sample_rate_hz_ = rtc::Optional<int>(); |
419 } | 417 } |
420 decoders_.erase(it); | 418 decoders_.erase(it); |
421 return 0; | 419 return 0; |
422 } | 420 } |
423 | 421 |
424 void AcmReceiver::set_id(int id) { | 422 void AcmReceiver::set_id(int id) { |
425 CriticalSectionScoped lock(crit_sect_.get()); | 423 rtc::CritScope lock(&crit_sect_); |
426 id_ = id; | 424 id_ = id; |
427 } | 425 } |
428 | 426 |
429 bool AcmReceiver::GetPlayoutTimestamp(uint32_t* timestamp) { | 427 bool AcmReceiver::GetPlayoutTimestamp(uint32_t* timestamp) { |
430 return neteq_->GetPlayoutTimestamp(timestamp); | 428 return neteq_->GetPlayoutTimestamp(timestamp); |
431 } | 429 } |
432 | 430 |
433 int AcmReceiver::LastAudioCodec(CodecInst* codec) const { | 431 int AcmReceiver::LastAudioCodec(CodecInst* codec) const { |
434 CriticalSectionScoped lock(crit_sect_.get()); | 432 rtc::CritScope lock(&crit_sect_); |
435 if (!last_audio_decoder_) { | 433 if (!last_audio_decoder_) { |
436 return -1; | 434 return -1; |
437 } | 435 } |
438 *codec = *RentACodec::CodecInstById( | 436 *codec = *RentACodec::CodecInstById( |
439 *RentACodec::CodecIdFromIndex(last_audio_decoder_->acm_codec_id)); | 437 *RentACodec::CodecIdFromIndex(last_audio_decoder_->acm_codec_id)); |
440 codec->pltype = last_audio_decoder_->payload_type; | 438 codec->pltype = last_audio_decoder_->payload_type; |
441 codec->channels = last_audio_decoder_->channels; | 439 codec->channels = last_audio_decoder_->channels; |
442 codec->plfreq = last_audio_decoder_->sample_rate_hz; | 440 codec->plfreq = last_audio_decoder_->sample_rate_hz; |
443 return 0; | 441 return 0; |
444 } | 442 } |
(...skipping 16 matching lines...) Expand all Loading... |
461 acm_stat->clockDriftPPM = neteq_stat.clockdrift_ppm; | 459 acm_stat->clockDriftPPM = neteq_stat.clockdrift_ppm; |
462 acm_stat->addedSamples = neteq_stat.added_zero_samples; | 460 acm_stat->addedSamples = neteq_stat.added_zero_samples; |
463 acm_stat->meanWaitingTimeMs = neteq_stat.mean_waiting_time_ms; | 461 acm_stat->meanWaitingTimeMs = neteq_stat.mean_waiting_time_ms; |
464 acm_stat->medianWaitingTimeMs = neteq_stat.median_waiting_time_ms; | 462 acm_stat->medianWaitingTimeMs = neteq_stat.median_waiting_time_ms; |
465 acm_stat->minWaitingTimeMs = neteq_stat.min_waiting_time_ms; | 463 acm_stat->minWaitingTimeMs = neteq_stat.min_waiting_time_ms; |
466 acm_stat->maxWaitingTimeMs = neteq_stat.max_waiting_time_ms; | 464 acm_stat->maxWaitingTimeMs = neteq_stat.max_waiting_time_ms; |
467 } | 465 } |
468 | 466 |
469 int AcmReceiver::DecoderByPayloadType(uint8_t payload_type, | 467 int AcmReceiver::DecoderByPayloadType(uint8_t payload_type, |
470 CodecInst* codec) const { | 468 CodecInst* codec) const { |
471 CriticalSectionScoped lock(crit_sect_.get()); | 469 rtc::CritScope lock(&crit_sect_); |
472 auto it = decoders_.find(payload_type); | 470 auto it = decoders_.find(payload_type); |
473 if (it == decoders_.end()) { | 471 if (it == decoders_.end()) { |
474 LOG(LERROR) << "AcmReceiver::DecoderByPayloadType " | 472 LOG(LERROR) << "AcmReceiver::DecoderByPayloadType " |
475 << static_cast<int>(payload_type); | 473 << static_cast<int>(payload_type); |
476 return -1; | 474 return -1; |
477 } | 475 } |
478 const Decoder& decoder = it->second; | 476 const Decoder& decoder = it->second; |
479 *codec = *RentACodec::CodecInstById( | 477 *codec = *RentACodec::CodecInstById( |
480 *RentACodec::CodecIdFromIndex(decoder.acm_codec_id)); | 478 *RentACodec::CodecIdFromIndex(decoder.acm_codec_id)); |
481 codec->pltype = decoder.payload_type; | 479 codec->pltype = decoder.payload_type; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 // We masked 6 most significant bits of 32-bit so there is no overflow in | 523 // We masked 6 most significant bits of 32-bit so there is no overflow in |
526 // the conversion from milliseconds to timestamp. | 524 // the conversion from milliseconds to timestamp. |
527 const uint32_t now_in_ms = static_cast<uint32_t>( | 525 const uint32_t now_in_ms = static_cast<uint32_t>( |
528 clock_->TimeInMilliseconds() & 0x03ffffff); | 526 clock_->TimeInMilliseconds() & 0x03ffffff); |
529 return static_cast<uint32_t>( | 527 return static_cast<uint32_t>( |
530 (decoder_sampling_rate / 1000) * now_in_ms); | 528 (decoder_sampling_rate / 1000) * now_in_ms); |
531 } | 529 } |
532 | 530 |
533 void AcmReceiver::GetDecodingCallStatistics( | 531 void AcmReceiver::GetDecodingCallStatistics( |
534 AudioDecodingCallStats* stats) const { | 532 AudioDecodingCallStats* stats) const { |
535 CriticalSectionScoped lock(crit_sect_.get()); | 533 rtc::CritScope lock(&crit_sect_); |
536 *stats = call_stats_.GetDecodingStatistics(); | 534 *stats = call_stats_.GetDecodingStatistics(); |
537 } | 535 } |
538 | 536 |
539 } // namespace acm2 | 537 } // namespace acm2 |
540 | 538 |
541 } // namespace webrtc | 539 } // namespace webrtc |
OLD | NEW |