Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 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 20 matching lines...) Expand all Loading... | |
| 31 vad(NULL) { | 31 vad(NULL) { |
| 32 } | 32 } |
| 33 | 33 |
| 34 bool AudioEncoderCng::Config::IsOk() const { | 34 bool AudioEncoderCng::Config::IsOk() const { |
| 35 if (num_channels != 1) | 35 if (num_channels != 1) |
| 36 return false; | 36 return false; |
| 37 if (!speech_encoder) | 37 if (!speech_encoder) |
| 38 return false; | 38 return false; |
| 39 if (num_channels != speech_encoder->NumChannels()) | 39 if (num_channels != speech_encoder->NumChannels()) |
| 40 return false; | 40 return false; |
| 41 if (sid_frame_interval_ms < speech_encoder->Max10MsFramesInAPacket() * 10) | 41 if (sid_frame_interval_ms < |
| 42 static_cast<int>(speech_encoder->Max10MsFramesInAPacket() * 10)) | |
| 42 return false; | 43 return false; |
| 43 if (num_cng_coefficients > WEBRTC_CNG_MAX_LPC_ORDER || | 44 if (num_cng_coefficients > WEBRTC_CNG_MAX_LPC_ORDER || |
| 44 num_cng_coefficients <= 0) | 45 num_cng_coefficients <= 0) |
| 45 return false; | 46 return false; |
| 46 return true; | 47 return true; |
| 47 } | 48 } |
| 48 | 49 |
| 49 AudioEncoderCng::AudioEncoderCng(const Config& config) | 50 AudioEncoderCng::AudioEncoderCng(const Config& config) |
| 50 : speech_encoder_(config.speech_encoder), | 51 : speech_encoder_(config.speech_encoder), |
| 51 cng_payload_type_(config.payload_type), | 52 cng_payload_type_(config.payload_type), |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 82 return 1; | 83 return 1; |
| 83 } | 84 } |
| 84 | 85 |
| 85 size_t AudioEncoderCng::MaxEncodedBytes() const { | 86 size_t AudioEncoderCng::MaxEncodedBytes() const { |
| 86 const size_t max_encoded_bytes_active = speech_encoder_->MaxEncodedBytes(); | 87 const size_t max_encoded_bytes_active = speech_encoder_->MaxEncodedBytes(); |
| 87 const size_t max_encoded_bytes_passive = | 88 const size_t max_encoded_bytes_passive = |
| 88 rtc::CheckedDivExact(kMaxFrameSizeMs, 10) * SamplesPer10msFrame(); | 89 rtc::CheckedDivExact(kMaxFrameSizeMs, 10) * SamplesPer10msFrame(); |
| 89 return std::max(max_encoded_bytes_active, max_encoded_bytes_passive); | 90 return std::max(max_encoded_bytes_active, max_encoded_bytes_passive); |
| 90 } | 91 } |
| 91 | 92 |
| 92 int AudioEncoderCng::Num10MsFramesInNextPacket() const { | 93 size_t AudioEncoderCng::Num10MsFramesInNextPacket() const { |
| 93 return speech_encoder_->Num10MsFramesInNextPacket(); | 94 return speech_encoder_->Num10MsFramesInNextPacket(); |
| 94 } | 95 } |
| 95 | 96 |
| 96 int AudioEncoderCng::Max10MsFramesInAPacket() const { | 97 size_t AudioEncoderCng::Max10MsFramesInAPacket() const { |
| 97 return speech_encoder_->Max10MsFramesInAPacket(); | 98 return speech_encoder_->Max10MsFramesInAPacket(); |
| 98 } | 99 } |
| 99 | 100 |
| 100 int AudioEncoderCng::GetTargetBitrate() const { | 101 int AudioEncoderCng::GetTargetBitrate() const { |
| 101 return speech_encoder_->GetTargetBitrate(); | 102 return speech_encoder_->GetTargetBitrate(); |
| 102 } | 103 } |
| 103 | 104 |
| 104 void AudioEncoderCng::SetTargetBitrate(int bits_per_second) { | 105 void AudioEncoderCng::SetTargetBitrate(int bits_per_second) { |
| 105 speech_encoder_->SetTargetBitrate(bits_per_second); | 106 speech_encoder_->SetTargetBitrate(bits_per_second); |
| 106 } | 107 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 117 size_t max_encoded_bytes, | 118 size_t max_encoded_bytes, |
| 118 uint8_t* encoded) { | 119 uint8_t* encoded) { |
| 119 CHECK_GE(max_encoded_bytes, static_cast<size_t>(num_cng_coefficients_ + 1)); | 120 CHECK_GE(max_encoded_bytes, static_cast<size_t>(num_cng_coefficients_ + 1)); |
| 120 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); | 121 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); |
| 121 CHECK_EQ(speech_buffer_.size(), | 122 CHECK_EQ(speech_buffer_.size(), |
| 122 rtp_timestamps_.size() * samples_per_10ms_frame); | 123 rtp_timestamps_.size() * samples_per_10ms_frame); |
| 123 rtp_timestamps_.push_back(rtp_timestamp); | 124 rtp_timestamps_.push_back(rtp_timestamp); |
| 124 for (size_t i = 0; i < samples_per_10ms_frame; ++i) { | 125 for (size_t i = 0; i < samples_per_10ms_frame; ++i) { |
| 125 speech_buffer_.push_back(audio[i]); | 126 speech_buffer_.push_back(audio[i]); |
| 126 } | 127 } |
| 127 const int frames_to_encode = speech_encoder_->Num10MsFramesInNextPacket(); | 128 const size_t frames_to_encode = speech_encoder_->Num10MsFramesInNextPacket(); |
| 128 if (rtp_timestamps_.size() < static_cast<size_t>(frames_to_encode)) { | 129 if (rtp_timestamps_.size() < frames_to_encode) { |
| 129 return EncodedInfo(); | 130 return EncodedInfo(); |
| 130 } | 131 } |
| 131 CHECK_LE(frames_to_encode * 10, kMaxFrameSizeMs) | 132 CHECK_LE(static_cast<int>(frames_to_encode * 10), kMaxFrameSizeMs) |
| 132 << "Frame size cannot be larger than " << kMaxFrameSizeMs | 133 << "Frame size cannot be larger than " << kMaxFrameSizeMs |
| 133 << " ms when using VAD/CNG."; | 134 << " ms when using VAD/CNG."; |
| 134 | 135 |
| 135 // Group several 10 ms blocks per VAD call. Call VAD once or twice using the | 136 // Group several 10 ms blocks per VAD call. Call VAD once or twice using the |
| 136 // following split sizes: | 137 // following split sizes: |
| 137 // 10 ms = 10 + 0 ms; 20 ms = 20 + 0 ms; 30 ms = 30 + 0 ms; | 138 // 10 ms = 10 + 0 ms; 20 ms = 20 + 0 ms; 30 ms = 30 + 0 ms; |
| 138 // 40 ms = 20 + 20 ms; 50 ms = 30 + 20 ms; 60 ms = 30 + 30 ms. | 139 // 40 ms = 20 + 20 ms; 50 ms = 30 + 20 ms; 60 ms = 30 + 30 ms. |
| 139 int blocks_in_first_vad_call = | 140 size_t blocks_in_first_vad_call = |
| 140 (frames_to_encode > 3 ? 3 : frames_to_encode); | 141 (frames_to_encode > 3 ? 3 : frames_to_encode); |
| 141 if (frames_to_encode == 4) | 142 if (frames_to_encode == 4) |
| 142 blocks_in_first_vad_call = 2; | 143 blocks_in_first_vad_call = 2; |
| 143 CHECK_GE(frames_to_encode, blocks_in_first_vad_call); | 144 CHECK_GE(frames_to_encode, blocks_in_first_vad_call); |
| 144 const int blocks_in_second_vad_call = | 145 const size_t blocks_in_second_vad_call = |
| 145 frames_to_encode - blocks_in_first_vad_call; | 146 frames_to_encode - blocks_in_first_vad_call; |
| 146 | 147 |
| 147 // Check if all of the buffer is passive speech. Start with checking the first | 148 // Check if all of the buffer is passive speech. Start with checking the first |
| 148 // block. | 149 // block. |
| 149 Vad::Activity activity = vad_->VoiceActivity( | 150 Vad::Activity activity = vad_->VoiceActivity( |
| 150 &speech_buffer_[0], samples_per_10ms_frame * blocks_in_first_vad_call, | 151 &speech_buffer_[0], samples_per_10ms_frame * blocks_in_first_vad_call, |
| 151 SampleRateHz()); | 152 SampleRateHz()); |
| 152 if (activity == Vad::kPassive && blocks_in_second_vad_call > 0) { | 153 if (activity == Vad::kPassive && blocks_in_second_vad_call > 0) { |
| 153 // Only check the second block if the first was passive. | 154 // Only check the second block if the first was passive. |
| 154 activity = vad_->VoiceActivity( | 155 activity = vad_->VoiceActivity( |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 176 | 177 |
| 177 speech_buffer_.erase( | 178 speech_buffer_.erase( |
| 178 speech_buffer_.begin(), | 179 speech_buffer_.begin(), |
| 179 speech_buffer_.begin() + frames_to_encode * samples_per_10ms_frame); | 180 speech_buffer_.begin() + frames_to_encode * samples_per_10ms_frame); |
| 180 rtp_timestamps_.erase(rtp_timestamps_.begin(), | 181 rtp_timestamps_.erase(rtp_timestamps_.begin(), |
| 181 rtp_timestamps_.begin() + frames_to_encode); | 182 rtp_timestamps_.begin() + frames_to_encode); |
| 182 return info; | 183 return info; |
| 183 } | 184 } |
| 184 | 185 |
| 185 AudioEncoder::EncodedInfo AudioEncoderCng::EncodePassive( | 186 AudioEncoder::EncodedInfo AudioEncoderCng::EncodePassive( |
| 186 int frames_to_encode, | 187 size_t frames_to_encode, |
| 187 size_t max_encoded_bytes, | 188 size_t max_encoded_bytes, |
| 188 uint8_t* encoded) { | 189 uint8_t* encoded) { |
| 189 bool force_sid = last_frame_active_; | 190 bool force_sid = last_frame_active_; |
| 190 bool output_produced = false; | 191 bool output_produced = false; |
| 191 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); | 192 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); |
| 192 CHECK_GE(max_encoded_bytes, frames_to_encode * samples_per_10ms_frame); | 193 CHECK_GE(max_encoded_bytes, frames_to_encode * samples_per_10ms_frame); |
| 193 AudioEncoder::EncodedInfo info; | 194 AudioEncoder::EncodedInfo info; |
| 194 for (int i = 0; i < frames_to_encode; ++i) { | 195 for (size_t i = 0; i < frames_to_encode; ++i) { |
| 195 int16_t encoded_bytes_tmp = 0; | 196 // It's important not to pass &info.encoded_bytes directly to |
| 197 // WebRtcCng_Encode(), since later loop iterations may return zero in that | |
| 198 // value, in which case we don't want to overwrite any value from an earlier | |
| 199 // iteration. | |
|
kwiberg-webrtc
2015/08/06 09:14:25
Not sure the comment says anything that isn't alre
Peter Kasting
2015/08/06 18:38:50
I wrote it because I did the wrong thing here orig
| |
| 200 size_t encoded_bytes_tmp = 0; | |
| 196 CHECK_GE(WebRtcCng_Encode(cng_inst_.get(), | 201 CHECK_GE(WebRtcCng_Encode(cng_inst_.get(), |
| 197 &speech_buffer_[i * samples_per_10ms_frame], | 202 &speech_buffer_[i * samples_per_10ms_frame], |
| 198 static_cast<int16_t>(samples_per_10ms_frame), | 203 samples_per_10ms_frame, |
| 199 encoded, &encoded_bytes_tmp, force_sid), 0); | 204 encoded, &encoded_bytes_tmp, force_sid), 0); |
| 200 if (encoded_bytes_tmp > 0) { | 205 if (encoded_bytes_tmp > 0) { |
| 201 CHECK(!output_produced); | 206 CHECK(!output_produced); |
| 202 info.encoded_bytes = static_cast<size_t>(encoded_bytes_tmp); | 207 info.encoded_bytes = encoded_bytes_tmp; |
| 203 output_produced = true; | 208 output_produced = true; |
| 204 force_sid = false; | 209 force_sid = false; |
| 205 } | 210 } |
| 206 } | 211 } |
| 207 info.encoded_timestamp = rtp_timestamps_.front(); | 212 info.encoded_timestamp = rtp_timestamps_.front(); |
| 208 info.payload_type = cng_payload_type_; | 213 info.payload_type = cng_payload_type_; |
| 209 info.send_even_if_empty = true; | 214 info.send_even_if_empty = true; |
| 210 info.speech = false; | 215 info.speech = false; |
| 211 return info; | 216 return info; |
| 212 } | 217 } |
| 213 | 218 |
| 214 AudioEncoder::EncodedInfo AudioEncoderCng::EncodeActive( | 219 AudioEncoder::EncodedInfo AudioEncoderCng::EncodeActive( |
| 215 int frames_to_encode, | 220 size_t frames_to_encode, |
| 216 size_t max_encoded_bytes, | 221 size_t max_encoded_bytes, |
| 217 uint8_t* encoded) { | 222 uint8_t* encoded) { |
| 218 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); | 223 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); |
| 219 AudioEncoder::EncodedInfo info; | 224 AudioEncoder::EncodedInfo info; |
| 220 for (int i = 0; i < frames_to_encode; ++i) { | 225 for (size_t i = 0; i < frames_to_encode; ++i) { |
| 221 info = speech_encoder_->Encode( | 226 info = speech_encoder_->Encode( |
| 222 rtp_timestamps_.front(), &speech_buffer_[i * samples_per_10ms_frame], | 227 rtp_timestamps_.front(), &speech_buffer_[i * samples_per_10ms_frame], |
| 223 samples_per_10ms_frame, max_encoded_bytes, encoded); | 228 samples_per_10ms_frame, max_encoded_bytes, encoded); |
| 224 if (i + 1 == frames_to_encode) { | 229 if (i + 1 == frames_to_encode) { |
| 225 CHECK_GT(info.encoded_bytes, 0u) << "Encoder didn't deliver data."; | 230 CHECK_GT(info.encoded_bytes, 0u) << "Encoder didn't deliver data."; |
| 226 } else { | 231 } else { |
| 227 CHECK_EQ(info.encoded_bytes, 0u) << "Encoder delivered data too early."; | 232 CHECK_EQ(info.encoded_bytes, 0u) << "Encoder delivered data too early."; |
| 228 } | 233 } |
| 229 } | 234 } |
| 230 return info; | 235 return info; |
| 231 } | 236 } |
| 232 | 237 |
| 233 size_t AudioEncoderCng::SamplesPer10msFrame() const { | 238 size_t AudioEncoderCng::SamplesPer10msFrame() const { |
| 234 return rtc::CheckedDivExact(10 * SampleRateHz(), 1000); | 239 return rtc::CheckedDivExact(10 * SampleRateHz(), 1000); |
| 235 } | 240 } |
| 236 | 241 |
| 237 } // namespace webrtc | 242 } // namespace webrtc |
| OLD | NEW |