| 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 |