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/include/audio_encoder_cng.h" | 11 #include "webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <limits> | 14 #include <limits> |
15 | 15 |
16 namespace webrtc { | 16 namespace webrtc { |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
20 const int kMaxFrameSizeMs = 60; | 20 const int kMaxFrameSizeMs = 60; |
21 | 21 |
| 22 rtc::scoped_ptr<CNG_enc_inst, CngInstDeleter> CreateCngInst( |
| 23 int sample_rate_hz, |
| 24 int sid_frame_interval_ms, |
| 25 int num_cng_coefficients) { |
| 26 rtc::scoped_ptr<CNG_enc_inst, CngInstDeleter> cng_inst; |
| 27 CHECK_EQ(0, WebRtcCng_CreateEnc(cng_inst.accept())); |
| 28 CHECK_EQ(0, WebRtcCng_InitEnc(cng_inst.get(), sample_rate_hz, |
| 29 sid_frame_interval_ms, num_cng_coefficients)); |
| 30 return cng_inst; |
| 31 } |
| 32 |
22 } // namespace | 33 } // namespace |
23 | 34 |
24 AudioEncoderCng::Config::Config() | |
25 : num_channels(1), | |
26 payload_type(13), | |
27 speech_encoder(NULL), | |
28 vad_mode(Vad::kVadNormal), | |
29 sid_frame_interval_ms(100), | |
30 num_cng_coefficients(8), | |
31 vad(NULL) { | |
32 } | |
33 | |
34 bool AudioEncoderCng::Config::IsOk() const { | 35 bool AudioEncoderCng::Config::IsOk() const { |
35 if (num_channels != 1) | 36 if (num_channels != 1) |
36 return false; | 37 return false; |
37 if (!speech_encoder) | 38 if (!speech_encoder) |
38 return false; | 39 return false; |
39 if (num_channels != speech_encoder->NumChannels()) | 40 if (num_channels != speech_encoder->NumChannels()) |
40 return false; | 41 return false; |
41 if (sid_frame_interval_ms < | 42 if (sid_frame_interval_ms < |
42 static_cast<int>(speech_encoder->Max10MsFramesInAPacket() * 10)) | 43 static_cast<int>(speech_encoder->Max10MsFramesInAPacket() * 10)) |
43 return false; | 44 return false; |
44 if (num_cng_coefficients > WEBRTC_CNG_MAX_LPC_ORDER || | 45 if (num_cng_coefficients > WEBRTC_CNG_MAX_LPC_ORDER || |
45 num_cng_coefficients <= 0) | 46 num_cng_coefficients <= 0) |
46 return false; | 47 return false; |
47 return true; | 48 return true; |
48 } | 49 } |
49 | 50 |
50 AudioEncoderCng::AudioEncoderCng(const Config& config) | 51 AudioEncoderCng::AudioEncoderCng(const Config& config) |
51 : speech_encoder_(config.speech_encoder), | 52 : speech_encoder_(config.speech_encoder), |
52 cng_payload_type_(config.payload_type), | 53 cng_payload_type_(config.payload_type), |
53 num_cng_coefficients_(config.num_cng_coefficients), | 54 num_cng_coefficients_(config.num_cng_coefficients), |
| 55 sid_frame_interval_ms_(config.sid_frame_interval_ms), |
54 last_frame_active_(true), | 56 last_frame_active_(true), |
55 vad_(new Vad(config.vad_mode)) { | 57 vad_(config.vad ? config.vad : new Vad(config.vad_mode)) { |
56 if (config.vad) { | |
57 // Replace default Vad object with user-provided one. | |
58 vad_.reset(config.vad); | |
59 } | |
60 CHECK(config.IsOk()) << "Invalid configuration."; | 58 CHECK(config.IsOk()) << "Invalid configuration."; |
61 CNG_enc_inst* cng_inst; | 59 cng_inst_ = CreateCngInst(SampleRateHz(), sid_frame_interval_ms_, |
62 CHECK_EQ(WebRtcCng_CreateEnc(&cng_inst), 0) << "WebRtcCng_CreateEnc failed."; | 60 num_cng_coefficients_); |
63 cng_inst_.reset(cng_inst); // Transfer ownership to scoped_ptr. | |
64 CHECK_EQ(WebRtcCng_InitEnc(cng_inst_.get(), SampleRateHz(), | |
65 config.sid_frame_interval_ms, | |
66 config.num_cng_coefficients), | |
67 0) | |
68 << "WebRtcCng_InitEnc failed"; | |
69 } | 61 } |
70 | 62 |
71 AudioEncoderCng::~AudioEncoderCng() { | 63 AudioEncoderCng::~AudioEncoderCng() = default; |
72 } | |
73 | |
74 int AudioEncoderCng::SampleRateHz() const { | |
75 return speech_encoder_->SampleRateHz(); | |
76 } | |
77 | |
78 int AudioEncoderCng::RtpTimestampRateHz() const { | |
79 return speech_encoder_->RtpTimestampRateHz(); | |
80 } | |
81 | |
82 int AudioEncoderCng::NumChannels() const { | |
83 return 1; | |
84 } | |
85 | 64 |
86 size_t AudioEncoderCng::MaxEncodedBytes() const { | 65 size_t AudioEncoderCng::MaxEncodedBytes() const { |
87 const size_t max_encoded_bytes_active = speech_encoder_->MaxEncodedBytes(); | 66 const size_t max_encoded_bytes_active = speech_encoder_->MaxEncodedBytes(); |
88 const size_t max_encoded_bytes_passive = | 67 const size_t max_encoded_bytes_passive = |
89 rtc::CheckedDivExact(kMaxFrameSizeMs, 10) * SamplesPer10msFrame(); | 68 rtc::CheckedDivExact(kMaxFrameSizeMs, 10) * SamplesPer10msFrame(); |
90 return std::max(max_encoded_bytes_active, max_encoded_bytes_passive); | 69 return std::max(max_encoded_bytes_active, max_encoded_bytes_passive); |
91 } | 70 } |
92 | 71 |
| 72 int AudioEncoderCng::SampleRateHz() const { |
| 73 return speech_encoder_->SampleRateHz(); |
| 74 } |
| 75 |
| 76 int AudioEncoderCng::NumChannels() const { |
| 77 return 1; |
| 78 } |
| 79 |
| 80 int AudioEncoderCng::RtpTimestampRateHz() const { |
| 81 return speech_encoder_->RtpTimestampRateHz(); |
| 82 } |
| 83 |
93 size_t AudioEncoderCng::Num10MsFramesInNextPacket() const { | 84 size_t AudioEncoderCng::Num10MsFramesInNextPacket() const { |
94 return speech_encoder_->Num10MsFramesInNextPacket(); | 85 return speech_encoder_->Num10MsFramesInNextPacket(); |
95 } | 86 } |
96 | 87 |
97 size_t AudioEncoderCng::Max10MsFramesInAPacket() const { | 88 size_t AudioEncoderCng::Max10MsFramesInAPacket() const { |
98 return speech_encoder_->Max10MsFramesInAPacket(); | 89 return speech_encoder_->Max10MsFramesInAPacket(); |
99 } | 90 } |
100 | 91 |
101 int AudioEncoderCng::GetTargetBitrate() const { | 92 int AudioEncoderCng::GetTargetBitrate() const { |
102 return speech_encoder_->GetTargetBitrate(); | 93 return speech_encoder_->GetTargetBitrate(); |
103 } | 94 } |
104 | 95 |
105 void AudioEncoderCng::SetTargetBitrate(int bits_per_second) { | |
106 speech_encoder_->SetTargetBitrate(bits_per_second); | |
107 } | |
108 | |
109 void AudioEncoderCng::SetProjectedPacketLossRate(double fraction) { | |
110 DCHECK_GE(fraction, 0.0); | |
111 DCHECK_LE(fraction, 1.0); | |
112 speech_encoder_->SetProjectedPacketLossRate(fraction); | |
113 } | |
114 | |
115 AudioEncoder::EncodedInfo AudioEncoderCng::EncodeInternal( | 96 AudioEncoder::EncodedInfo AudioEncoderCng::EncodeInternal( |
116 uint32_t rtp_timestamp, | 97 uint32_t rtp_timestamp, |
117 const int16_t* audio, | 98 const int16_t* audio, |
118 size_t max_encoded_bytes, | 99 size_t max_encoded_bytes, |
119 uint8_t* encoded) { | 100 uint8_t* encoded) { |
120 CHECK_GE(max_encoded_bytes, static_cast<size_t>(num_cng_coefficients_ + 1)); | 101 CHECK_GE(max_encoded_bytes, static_cast<size_t>(num_cng_coefficients_ + 1)); |
121 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); | 102 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); |
122 CHECK_EQ(speech_buffer_.size(), | 103 CHECK_EQ(speech_buffer_.size(), |
123 rtp_timestamps_.size() * samples_per_10ms_frame); | 104 rtp_timestamps_.size() * samples_per_10ms_frame); |
124 rtp_timestamps_.push_back(rtp_timestamp); | 105 rtp_timestamps_.push_back(rtp_timestamp); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 } | 157 } |
177 | 158 |
178 speech_buffer_.erase( | 159 speech_buffer_.erase( |
179 speech_buffer_.begin(), | 160 speech_buffer_.begin(), |
180 speech_buffer_.begin() + frames_to_encode * samples_per_10ms_frame); | 161 speech_buffer_.begin() + frames_to_encode * samples_per_10ms_frame); |
181 rtp_timestamps_.erase(rtp_timestamps_.begin(), | 162 rtp_timestamps_.erase(rtp_timestamps_.begin(), |
182 rtp_timestamps_.begin() + frames_to_encode); | 163 rtp_timestamps_.begin() + frames_to_encode); |
183 return info; | 164 return info; |
184 } | 165 } |
185 | 166 |
| 167 void AudioEncoderCng::Reset() { |
| 168 speech_encoder_->Reset(); |
| 169 speech_buffer_.clear(); |
| 170 rtp_timestamps_.clear(); |
| 171 last_frame_active_ = true; |
| 172 vad_->Reset(); |
| 173 cng_inst_ = CreateCngInst(SampleRateHz(), sid_frame_interval_ms_, |
| 174 num_cng_coefficients_); |
| 175 } |
| 176 |
| 177 bool AudioEncoderCng::SetFec(bool enable) { |
| 178 return speech_encoder_->SetFec(enable); |
| 179 } |
| 180 |
| 181 bool AudioEncoderCng::SetDtx(bool enable) { |
| 182 return speech_encoder_->SetDtx(enable); |
| 183 } |
| 184 |
| 185 bool AudioEncoderCng::SetApplication(Application application) { |
| 186 return speech_encoder_->SetApplication(application); |
| 187 } |
| 188 |
| 189 bool AudioEncoderCng::SetMaxPlaybackRate(int frequency_hz) { |
| 190 return speech_encoder_->SetMaxPlaybackRate(frequency_hz); |
| 191 } |
| 192 |
| 193 void AudioEncoderCng::SetProjectedPacketLossRate(double fraction) { |
| 194 speech_encoder_->SetProjectedPacketLossRate(fraction); |
| 195 } |
| 196 |
| 197 void AudioEncoderCng::SetTargetBitrate(int bits_per_second) { |
| 198 speech_encoder_->SetTargetBitrate(bits_per_second); |
| 199 } |
| 200 |
| 201 void AudioEncoderCng::SetMaxBitrate(int max_bps) { |
| 202 speech_encoder_->SetMaxBitrate(max_bps); |
| 203 } |
| 204 |
| 205 void AudioEncoderCng::SetMaxPayloadSize(int max_payload_size_bytes) { |
| 206 speech_encoder_->SetMaxPayloadSize(max_payload_size_bytes); |
| 207 } |
| 208 |
186 AudioEncoder::EncodedInfo AudioEncoderCng::EncodePassive( | 209 AudioEncoder::EncodedInfo AudioEncoderCng::EncodePassive( |
187 size_t frames_to_encode, | 210 size_t frames_to_encode, |
188 size_t max_encoded_bytes, | 211 size_t max_encoded_bytes, |
189 uint8_t* encoded) { | 212 uint8_t* encoded) { |
190 bool force_sid = last_frame_active_; | 213 bool force_sid = last_frame_active_; |
191 bool output_produced = false; | 214 bool output_produced = false; |
192 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); | 215 const size_t samples_per_10ms_frame = SamplesPer10msFrame(); |
193 CHECK_GE(max_encoded_bytes, frames_to_encode * samples_per_10ms_frame); | 216 CHECK_GE(max_encoded_bytes, frames_to_encode * samples_per_10ms_frame); |
194 AudioEncoder::EncodedInfo info; | 217 AudioEncoder::EncodedInfo info; |
195 for (size_t i = 0; i < frames_to_encode; ++i) { | 218 for (size_t i = 0; i < frames_to_encode; ++i) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 } | 256 } |
234 } | 257 } |
235 return info; | 258 return info; |
236 } | 259 } |
237 | 260 |
238 size_t AudioEncoderCng::SamplesPer10msFrame() const { | 261 size_t AudioEncoderCng::SamplesPer10msFrame() const { |
239 return rtc::CheckedDivExact(10 * SampleRateHz(), 1000); | 262 return rtc::CheckedDivExact(10 * SampleRateHz(), 1000); |
240 } | 263 } |
241 | 264 |
242 } // namespace webrtc | 265 } // namespace webrtc |
OLD | NEW |