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 |
11 #include "webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h" | 11 #include "webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <memory> | 14 #include <memory> |
15 #include <limits> | 15 #include <limits> |
16 #include <utility> | 16 #include <utility> |
17 | 17 |
18 namespace webrtc { | 18 namespace webrtc { |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
22 const int kMaxFrameSizeMs = 60; | 22 const int kMaxFrameSizeMs = 60; |
23 | 23 |
24 std::unique_ptr<CNG_enc_inst, CngInstDeleter> CreateCngInst( | |
25 int sample_rate_hz, | |
26 int sid_frame_interval_ms, | |
27 int num_cng_coefficients) { | |
28 CNG_enc_inst* ci; | |
29 RTC_CHECK_EQ(0, WebRtcCng_CreateEnc(&ci)); | |
30 std::unique_ptr<CNG_enc_inst, CngInstDeleter> cng_inst(ci); | |
31 RTC_CHECK_EQ(0, | |
32 WebRtcCng_InitEnc(cng_inst.get(), sample_rate_hz, | |
33 sid_frame_interval_ms, num_cng_coefficients)); | |
34 return cng_inst; | |
35 } | |
36 | |
37 } // namespace | 24 } // namespace |
38 | 25 |
39 AudioEncoderCng::Config::Config() = default; | 26 AudioEncoderCng::Config::Config() = default; |
40 AudioEncoderCng::Config::Config(Config&&) = default; | 27 AudioEncoderCng::Config::Config(Config&&) = default; |
41 AudioEncoderCng::Config::~Config() = default; | 28 AudioEncoderCng::Config::~Config() = default; |
42 | 29 |
43 bool AudioEncoderCng::Config::IsOk() const { | 30 bool AudioEncoderCng::Config::IsOk() const { |
44 if (num_channels != 1) | 31 if (num_channels != 1) |
45 return false; | 32 return false; |
46 if (!speech_encoder) | 33 if (!speech_encoder) |
(...skipping 11 matching lines...) Expand all Loading... |
58 | 45 |
59 AudioEncoderCng::AudioEncoderCng(Config&& config) | 46 AudioEncoderCng::AudioEncoderCng(Config&& config) |
60 : speech_encoder_( | 47 : speech_encoder_( |
61 ([&] { RTC_CHECK(config.IsOk()) << "Invalid configuration."; }(), | 48 ([&] { RTC_CHECK(config.IsOk()) << "Invalid configuration."; }(), |
62 std::move(config.speech_encoder))), | 49 std::move(config.speech_encoder))), |
63 cng_payload_type_(config.payload_type), | 50 cng_payload_type_(config.payload_type), |
64 num_cng_coefficients_(config.num_cng_coefficients), | 51 num_cng_coefficients_(config.num_cng_coefficients), |
65 sid_frame_interval_ms_(config.sid_frame_interval_ms), | 52 sid_frame_interval_ms_(config.sid_frame_interval_ms), |
66 last_frame_active_(true), | 53 last_frame_active_(true), |
67 vad_(config.vad ? std::unique_ptr<Vad>(config.vad) | 54 vad_(config.vad ? std::unique_ptr<Vad>(config.vad) |
68 : CreateVad(config.vad_mode)) { | 55 : CreateVad(config.vad_mode)), |
69 cng_inst_ = CreateCngInst(SampleRateHz(), sid_frame_interval_ms_, | 56 cng_encoder_(new ComfortNoiseEncoder(SampleRateHz(), |
70 num_cng_coefficients_); | 57 sid_frame_interval_ms_, |
| 58 num_cng_coefficients_)) { |
71 } | 59 } |
72 | 60 |
73 AudioEncoderCng::~AudioEncoderCng() = default; | 61 AudioEncoderCng::~AudioEncoderCng() = default; |
74 | 62 |
75 int AudioEncoderCng::SampleRateHz() const { | 63 int AudioEncoderCng::SampleRateHz() const { |
76 return speech_encoder_->SampleRateHz(); | 64 return speech_encoder_->SampleRateHz(); |
77 } | 65 } |
78 | 66 |
79 size_t AudioEncoderCng::NumChannels() const { | 67 size_t AudioEncoderCng::NumChannels() const { |
80 return 1; | 68 return 1; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 rtp_timestamps_.begin() + frames_to_encode); | 151 rtp_timestamps_.begin() + frames_to_encode); |
164 return info; | 152 return info; |
165 } | 153 } |
166 | 154 |
167 void AudioEncoderCng::Reset() { | 155 void AudioEncoderCng::Reset() { |
168 speech_encoder_->Reset(); | 156 speech_encoder_->Reset(); |
169 speech_buffer_.clear(); | 157 speech_buffer_.clear(); |
170 rtp_timestamps_.clear(); | 158 rtp_timestamps_.clear(); |
171 last_frame_active_ = true; | 159 last_frame_active_ = true; |
172 vad_->Reset(); | 160 vad_->Reset(); |
173 cng_inst_ = CreateCngInst(SampleRateHz(), sid_frame_interval_ms_, | 161 cng_encoder_.reset( |
174 num_cng_coefficients_); | 162 new ComfortNoiseEncoder(SampleRateHz(), sid_frame_interval_ms_, |
| 163 num_cng_coefficients_)); |
175 } | 164 } |
176 | 165 |
177 bool AudioEncoderCng::SetFec(bool enable) { | 166 bool AudioEncoderCng::SetFec(bool enable) { |
178 return speech_encoder_->SetFec(enable); | 167 return speech_encoder_->SetFec(enable); |
179 } | 168 } |
180 | 169 |
181 bool AudioEncoderCng::SetDtx(bool enable) { | 170 bool AudioEncoderCng::SetDtx(bool enable) { |
182 return speech_encoder_->SetDtx(enable); | 171 return speech_encoder_->SetDtx(enable); |
183 } | 172 } |
184 | 173 |
(...skipping 12 matching lines...) Expand all Loading... |
197 void AudioEncoderCng::SetTargetBitrate(int bits_per_second) { | 186 void AudioEncoderCng::SetTargetBitrate(int bits_per_second) { |
198 speech_encoder_->SetTargetBitrate(bits_per_second); | 187 speech_encoder_->SetTargetBitrate(bits_per_second); |
199 } | 188 } |
200 | 189 |
201 AudioEncoder::EncodedInfo AudioEncoderCng::EncodePassive( | 190 AudioEncoder::EncodedInfo AudioEncoderCng::EncodePassive( |
202 size_t frames_to_encode, | 191 size_t frames_to_encode, |
203 rtc::Buffer* encoded) { | 192 rtc::Buffer* encoded) { |
204 bool force_sid = last_frame_active_; | 193 bool force_sid = last_frame_active_; |
205 bool output_produced = false; | 194 bool output_produced = false; |
206 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); | 195 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); |
207 const size_t bytes_to_encode = frames_to_encode * samples_per_10ms_frame; | |
208 AudioEncoder::EncodedInfo info; | 196 AudioEncoder::EncodedInfo info; |
209 | 197 |
210 encoded->AppendData(bytes_to_encode, [&] (rtc::ArrayView<uint8_t> encoded) { | 198 for (size_t i = 0; i < frames_to_encode; ++i) { |
211 for (size_t i = 0; i < frames_to_encode; ++i) { | 199 // It's important not to pass &info.encoded_bytes directly to |
212 // It's important not to pass &info.encoded_bytes directly to | 200 // WebRtcCng_Encode(), since later loop iterations may return zero in |
213 // WebRtcCng_Encode(), since later loop iterations may return zero in | 201 // that value, in which case we don't want to overwrite any value from |
214 // that value, in which case we don't want to overwrite any value from | 202 // an earlier iteration. |
215 // an earlier iteration. | 203 size_t encoded_bytes_tmp = |
216 size_t encoded_bytes_tmp = 0; | 204 cng_encoder_->Encode( |
217 RTC_CHECK_GE( | 205 rtc::ArrayView<const int16_t>( |
218 WebRtcCng_Encode(cng_inst_.get(), | 206 &speech_buffer_[i * samples_per_10ms_frame], |
219 &speech_buffer_[i * samples_per_10ms_frame], | 207 samples_per_10ms_frame), |
220 samples_per_10ms_frame, encoded.data(), | 208 force_sid, encoded); |
221 &encoded_bytes_tmp, force_sid), | |
222 0); | |
223 if (encoded_bytes_tmp > 0) { | |
224 RTC_CHECK(!output_produced); | |
225 info.encoded_bytes = encoded_bytes_tmp; | |
226 output_produced = true; | |
227 force_sid = false; | |
228 } | |
229 } | |
230 | 209 |
231 return info.encoded_bytes; | 210 if (encoded_bytes_tmp > 0) { |
232 }); | 211 RTC_CHECK(!output_produced); |
| 212 info.encoded_bytes = encoded_bytes_tmp; |
| 213 output_produced = true; |
| 214 force_sid = false; |
| 215 } |
| 216 } |
233 | 217 |
234 info.encoded_timestamp = rtp_timestamps_.front(); | 218 info.encoded_timestamp = rtp_timestamps_.front(); |
235 info.payload_type = cng_payload_type_; | 219 info.payload_type = cng_payload_type_; |
236 info.send_even_if_empty = true; | 220 info.send_even_if_empty = true; |
237 info.speech = false; | 221 info.speech = false; |
238 return info; | 222 return info; |
239 } | 223 } |
240 | 224 |
241 AudioEncoder::EncodedInfo AudioEncoderCng::EncodeActive( | 225 AudioEncoder::EncodedInfo AudioEncoderCng::EncodeActive( |
242 size_t frames_to_encode, | 226 size_t frames_to_encode, |
(...skipping 15 matching lines...) Expand all Loading... |
258 } | 242 } |
259 } | 243 } |
260 return info; | 244 return info; |
261 } | 245 } |
262 | 246 |
263 size_t AudioEncoderCng::SamplesPer10msFrame() const { | 247 size_t AudioEncoderCng::SamplesPer10msFrame() const { |
264 return rtc::CheckedDivExact(10 * SampleRateHz(), 1000); | 248 return rtc::CheckedDivExact(10 * SampleRateHz(), 1000); |
265 } | 249 } |
266 | 250 |
267 } // namespace webrtc | 251 } // namespace webrtc |
OLD | NEW |