| 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/base/safe_conversions.h" |
| 21 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
y.h" | 22 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
y.h" |
| 22 #include "webrtc/common_types.h" | 23 #include "webrtc/common_types.h" |
| 23 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" | 24 #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" |
| 24 #include "webrtc/modules/audio_coding/acm2/acm_resampler.h" | 25 #include "webrtc/modules/audio_coding/acm2/acm_resampler.h" |
| 25 #include "webrtc/modules/audio_coding/acm2/call_statistics.h" | 26 #include "webrtc/modules/audio_coding/acm2/call_statistics.h" |
| 26 #include "webrtc/modules/audio_coding/neteq/include/neteq.h" | 27 #include "webrtc/modules/audio_coding/neteq/include/neteq.h" |
| 27 #include "webrtc/system_wrappers/include/clock.h" | 28 #include "webrtc/system_wrappers/include/clock.h" |
| 28 #include "webrtc/system_wrappers/include/tick_util.h" | 29 #include "webrtc/system_wrappers/include/tick_util.h" |
| 29 #include "webrtc/system_wrappers/include/trace.h" | 30 #include "webrtc/system_wrappers/include/trace.h" |
| 30 | 31 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 *i == RentACodec::CodecId::kCNSWB || | 115 *i == RentACodec::CodecId::kCNSWB || |
| 115 *i == RentACodec::CodecId::kCNFB)); | 116 *i == RentACodec::CodecId::kCNFB)); |
| 116 } | 117 } |
| 117 | 118 |
| 118 } // namespace | 119 } // namespace |
| 119 | 120 |
| 120 AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config) | 121 AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config) |
| 121 : id_(config.id), | 122 : id_(config.id), |
| 122 last_audio_decoder_(nullptr), | 123 last_audio_decoder_(nullptr), |
| 123 previous_audio_activity_(AudioFrame::kVadPassive), | 124 previous_audio_activity_(AudioFrame::kVadPassive), |
| 124 audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), | |
| 125 last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), | 125 last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), |
| 126 neteq_(NetEq::Create(config.neteq_config)), | 126 neteq_(NetEq::Create(config.neteq_config)), |
| 127 vad_enabled_(config.neteq_config.enable_post_decode_vad), | 127 vad_enabled_(config.neteq_config.enable_post_decode_vad), |
| 128 clock_(config.clock), | 128 clock_(config.clock), |
| 129 resampled_last_output_frame_(true) { | 129 resampled_last_output_frame_(true) { |
| 130 assert(clock_); | 130 assert(clock_); |
| 131 memset(audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples); | |
| 132 memset(last_audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples); | 131 memset(last_audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples); |
| 133 } | 132 } |
| 134 | 133 |
| 135 AcmReceiver::~AcmReceiver() { | 134 AcmReceiver::~AcmReceiver() { |
| 136 delete neteq_; | 135 delete neteq_; |
| 137 } | 136 } |
| 138 | 137 |
| 139 int AcmReceiver::SetMinimumDelay(int delay_ms) { | 138 int AcmReceiver::SetMinimumDelay(int delay_ms) { |
| 140 if (neteq_->SetMinimumDelay(delay_ms)) | 139 if (neteq_->SetMinimumDelay(delay_ms)) |
| 141 return 0; | 140 return 0; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 0) { | 201 0) { |
| 203 LOG(LERROR) << "AcmReceiver::InsertPacket " | 202 LOG(LERROR) << "AcmReceiver::InsertPacket " |
| 204 << static_cast<int>(header->payloadType) | 203 << static_cast<int>(header->payloadType) |
| 205 << " Failed to insert packet"; | 204 << " Failed to insert packet"; |
| 206 return -1; | 205 return -1; |
| 207 } | 206 } |
| 208 return 0; | 207 return 0; |
| 209 } | 208 } |
| 210 | 209 |
| 211 int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) { | 210 int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) { |
| 212 enum NetEqOutputType type; | |
| 213 size_t samples_per_channel; | |
| 214 size_t num_channels; | |
| 215 | |
| 216 // Accessing members, take the lock. | 211 // Accessing members, take the lock. |
| 217 rtc::CritScope lock(&crit_sect_); | 212 rtc::CritScope lock(&crit_sect_); |
| 218 | 213 |
| 219 // Always write the output to |audio_buffer_| first. | 214 enum NetEqOutputType type; |
| 220 if (neteq_->GetAudio(AudioFrame::kMaxDataSizeSamples, | 215 if (neteq_->GetAudio(audio_frame, &type) != NetEq::kOK) { |
| 221 audio_buffer_.get(), | |
| 222 &samples_per_channel, | |
| 223 &num_channels, | |
| 224 &type) != NetEq::kOK) { | |
| 225 LOG(LERROR) << "AcmReceiver::GetAudio - NetEq Failed."; | 216 LOG(LERROR) << "AcmReceiver::GetAudio - NetEq Failed."; |
| 226 return -1; | 217 return -1; |
| 227 } | 218 } |
| 228 | 219 |
| 229 const int current_sample_rate_hz = neteq_->last_output_sample_rate_hz(); | 220 const int current_sample_rate_hz = neteq_->last_output_sample_rate_hz(); |
| 230 | 221 |
| 231 // Update if resampling is required. | 222 // Update if resampling is required. |
| 232 const bool need_resampling = | 223 const bool need_resampling = |
| 233 (desired_freq_hz != -1) && (current_sample_rate_hz != desired_freq_hz); | 224 (desired_freq_hz != -1) && (current_sample_rate_hz != desired_freq_hz); |
| 234 | 225 |
| 235 if (need_resampling && !resampled_last_output_frame_) { | 226 if (need_resampling && !resampled_last_output_frame_) { |
| 236 // Prime the resampler with the last frame. | 227 // Prime the resampler with the last frame. |
| 237 int16_t temp_output[AudioFrame::kMaxDataSizeSamples]; | 228 int16_t temp_output[AudioFrame::kMaxDataSizeSamples]; |
| 238 int samples_per_channel_int = resampler_.Resample10Msec( | 229 int samples_per_channel_int = resampler_.Resample10Msec( |
| 239 last_audio_buffer_.get(), current_sample_rate_hz, desired_freq_hz, | 230 last_audio_buffer_.get(), current_sample_rate_hz, desired_freq_hz, |
| 240 num_channels, AudioFrame::kMaxDataSizeSamples, temp_output); | 231 audio_frame->num_channels_, AudioFrame::kMaxDataSizeSamples, |
| 232 temp_output); |
| 241 if (samples_per_channel_int < 0) { | 233 if (samples_per_channel_int < 0) { |
| 242 LOG(LERROR) << "AcmReceiver::GetAudio - " | 234 LOG(LERROR) << "AcmReceiver::GetAudio - " |
| 243 "Resampling last_audio_buffer_ failed."; | 235 "Resampling last_audio_buffer_ failed."; |
| 244 return -1; | 236 return -1; |
| 245 } | 237 } |
| 246 samples_per_channel = static_cast<size_t>(samples_per_channel_int); | |
| 247 } | 238 } |
| 248 | 239 |
| 249 // The audio in |audio_buffer_| is tansferred to |audio_frame_| below, either | |
| 250 // through resampling, or through straight memcpy. | |
| 251 // TODO(henrik.lundin) Glitches in the output may appear if the output rate | 240 // TODO(henrik.lundin) Glitches in the output may appear if the output rate |
| 252 // from NetEq changes. See WebRTC issue 3923. | 241 // from NetEq changes. See WebRTC issue 3923. |
| 253 if (need_resampling) { | 242 if (need_resampling) { |
| 254 int samples_per_channel_int = resampler_.Resample10Msec( | 243 int samples_per_channel_int = resampler_.Resample10Msec( |
| 255 audio_buffer_.get(), current_sample_rate_hz, desired_freq_hz, | 244 audio_frame->data_, current_sample_rate_hz, desired_freq_hz, |
| 256 num_channels, AudioFrame::kMaxDataSizeSamples, audio_frame->data_); | 245 audio_frame->num_channels_, AudioFrame::kMaxDataSizeSamples, |
| 246 audio_frame->data_); |
| 257 if (samples_per_channel_int < 0) { | 247 if (samples_per_channel_int < 0) { |
| 258 LOG(LERROR) << "AcmReceiver::GetAudio - Resampling audio_buffer_ failed."; | 248 LOG(LERROR) << "AcmReceiver::GetAudio - Resampling audio_buffer_ failed."; |
| 259 return -1; | 249 return -1; |
| 260 } | 250 } |
| 261 samples_per_channel = static_cast<size_t>(samples_per_channel_int); | 251 audio_frame->samples_per_channel_ = |
| 252 static_cast<size_t>(samples_per_channel_int); |
| 253 audio_frame->sample_rate_hz_ = desired_freq_hz; |
| 254 RTC_DCHECK_EQ( |
| 255 audio_frame->sample_rate_hz_, |
| 256 rtc::checked_cast<int>(audio_frame->samples_per_channel_ * 100)); |
| 262 resampled_last_output_frame_ = true; | 257 resampled_last_output_frame_ = true; |
| 263 } else { | 258 } else { |
| 264 resampled_last_output_frame_ = false; | 259 resampled_last_output_frame_ = false; |
| 265 // We might end up here ONLY if codec is changed. | 260 // We might end up here ONLY if codec is changed. |
| 266 memcpy(audio_frame->data_, | |
| 267 audio_buffer_.get(), | |
| 268 samples_per_channel * num_channels * sizeof(int16_t)); | |
| 269 } | 261 } |
| 270 | 262 |
| 271 // Swap buffers, so that the current audio is stored in |last_audio_buffer_| | 263 // Store current audio in |last_audio_buffer_| for next time. |
| 272 // for next time. | 264 memcpy(last_audio_buffer_.get(), audio_frame->data_, |
| 273 audio_buffer_.swap(last_audio_buffer_); | 265 sizeof(int16_t) * audio_frame->samples_per_channel_ * |
| 274 | 266 audio_frame->num_channels_); |
| 275 audio_frame->num_channels_ = num_channels; | |
| 276 audio_frame->samples_per_channel_ = samples_per_channel; | |
| 277 audio_frame->sample_rate_hz_ = static_cast<int>(samples_per_channel * 100); | |
| 278 | 267 |
| 279 // Should set |vad_activity| before calling SetAudioFrameActivityAndType(). | 268 // Should set |vad_activity| before calling SetAudioFrameActivityAndType(). |
| 280 audio_frame->vad_activity_ = previous_audio_activity_; | 269 audio_frame->vad_activity_ = previous_audio_activity_; |
| 281 SetAudioFrameActivityAndType(vad_enabled_, type, audio_frame); | 270 SetAudioFrameActivityAndType(vad_enabled_, type, audio_frame); |
| 282 previous_audio_activity_ = audio_frame->vad_activity_; | 271 previous_audio_activity_ = audio_frame->vad_activity_; |
| 283 call_stats_.DecodedByNetEq(audio_frame->speech_type_); | 272 call_stats_.DecodedByNetEq(audio_frame->speech_type_); |
| 284 | 273 |
| 285 // Computes the RTP timestamp of the first sample in |audio_frame| from | 274 // Computes the RTP timestamp of the first sample in |audio_frame| from |
| 286 // |GetPlayoutTimestamp|, which is the timestamp of the last sample of | 275 // |GetPlayoutTimestamp|, which is the timestamp of the last sample of |
| 287 // |audio_frame|. | 276 // |audio_frame|. |
| 277 // TODO(henrik.lundin) Move setting of audio_frame->timestamp_ inside NetEq. |
| 288 uint32_t playout_timestamp = 0; | 278 uint32_t playout_timestamp = 0; |
| 289 if (GetPlayoutTimestamp(&playout_timestamp)) { | 279 if (GetPlayoutTimestamp(&playout_timestamp)) { |
| 290 audio_frame->timestamp_ = playout_timestamp - | 280 audio_frame->timestamp_ = playout_timestamp - |
| 291 static_cast<uint32_t>(audio_frame->samples_per_channel_); | 281 static_cast<uint32_t>(audio_frame->samples_per_channel_); |
| 292 } else { | 282 } else { |
| 293 // Remain 0 until we have a valid |playout_timestamp|. | 283 // Remain 0 until we have a valid |playout_timestamp|. |
| 294 audio_frame->timestamp_ = 0; | 284 audio_frame->timestamp_ = 0; |
| 295 } | 285 } |
| 296 | 286 |
| 297 return 0; | 287 return 0; |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 | 520 |
| 531 void AcmReceiver::GetDecodingCallStatistics( | 521 void AcmReceiver::GetDecodingCallStatistics( |
| 532 AudioDecodingCallStats* stats) const { | 522 AudioDecodingCallStats* stats) const { |
| 533 rtc::CritScope lock(&crit_sect_); | 523 rtc::CritScope lock(&crit_sect_); |
| 534 *stats = call_stats_.GetDecodingStatistics(); | 524 *stats = call_stats_.GetDecodingStatistics(); |
| 535 } | 525 } |
| 536 | 526 |
| 537 } // namespace acm2 | 527 } // namespace acm2 |
| 538 | 528 |
| 539 } // namespace webrtc | 529 } // namespace webrtc |
| OLD | NEW |