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 |