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 |
| 11 #include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h" | 11 #include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h" |
| 12 | 12 |
| 13 #include <algorithm> | 13 #include <algorithm> |
| 14 | 14 |
| 15 #include "webrtc/base/arraysize.h" | |
| 15 #include "webrtc/base/checks.h" | 16 #include "webrtc/base/checks.h" |
| 16 #include "webrtc/base/safe_conversions.h" | 17 #include "webrtc/base/safe_conversions.h" |
| 17 #include "webrtc/common_types.h" | 18 #include "webrtc/common_types.h" |
| 19 #include "webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adapto r_impl.h" | |
| 20 #include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h " | |
| 18 #include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h" | 21 #include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h" |
| 22 #include "webrtc/system_wrappers/include/clock.h" | |
| 19 | 23 |
| 20 namespace webrtc { | 24 namespace webrtc { |
| 21 | 25 |
| 22 namespace { | 26 namespace { |
| 23 | 27 |
| 24 const int kSampleRateHz = 48000; | 28 const int kSampleRateHz = 48000; |
| 25 const int kMinBitrateBps = 500; | 29 const int kMinBitrateBps = 500; |
| 26 const int kMaxBitrateBps = 512000; | 30 const int kMaxBitrateBps = 512000; |
| 31 constexpr int kSupportedFrameLengths[] = {20, 60}; | |
| 27 | 32 |
| 28 AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) { | 33 AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) { |
| 29 AudioEncoderOpus::Config config; | 34 AudioEncoderOpus::Config config; |
| 30 config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48); | 35 config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48); |
| 31 config.num_channels = codec_inst.channels; | 36 config.num_channels = codec_inst.channels; |
| 32 config.bitrate_bps = rtc::Optional<int>(codec_inst.rate); | 37 config.bitrate_bps = rtc::Optional<int>(codec_inst.rate); |
| 33 config.payload_type = codec_inst.pltype; | 38 config.payload_type = codec_inst.pltype; |
| 34 config.application = config.num_channels == 1 ? AudioEncoderOpus::kVoip | 39 config.application = config.num_channels == 1 ? AudioEncoderOpus::kVoip |
| 35 : AudioEncoderOpus::kAudio; | 40 : AudioEncoderOpus::kAudio; |
| 36 return config; | 41 return config; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 97 } | 102 } |
| 98 | 103 |
| 99 int AudioEncoderOpus::Config::GetBitrateBps() const { | 104 int AudioEncoderOpus::Config::GetBitrateBps() const { |
| 100 RTC_DCHECK(IsOk()); | 105 RTC_DCHECK(IsOk()); |
| 101 if (bitrate_bps) | 106 if (bitrate_bps) |
| 102 return *bitrate_bps; // Explicitly set value. | 107 return *bitrate_bps; // Explicitly set value. |
| 103 else | 108 else |
| 104 return num_channels == 1 ? 32000 : 64000; // Default value. | 109 return num_channels == 1 ? 32000 : 64000; // Default value. |
| 105 } | 110 } |
| 106 | 111 |
| 107 AudioEncoderOpus::AudioEncoderOpus(const Config& config) | 112 AudioEncoderOpus::AudioEncoderOpus( |
| 108 : packet_loss_rate_(0.0), inst_(nullptr) { | 113 const Config& config, |
| 114 std::unique_ptr<AudioNetworkAdaptor> audio_network_adaptor) | |
| 115 : packet_loss_rate_(0.0), | |
| 116 inst_(nullptr), | |
| 117 audio_network_adaptor_(std::move(audio_network_adaptor)) { | |
|
kwiberg-webrtc
2016/10/03 12:48:10
You still take the ANA as an argument in the const
minyue-webrtc
2016/10/03 12:57:15
This ctor is only used for integration test. I thi
| |
| 109 RTC_CHECK(RecreateEncoderInstance(config)); | 118 RTC_CHECK(RecreateEncoderInstance(config)); |
| 110 } | 119 } |
| 111 | 120 |
| 112 AudioEncoderOpus::AudioEncoderOpus(const CodecInst& codec_inst) | 121 AudioEncoderOpus::AudioEncoderOpus(const CodecInst& codec_inst) |
| 113 : AudioEncoderOpus(CreateConfig(codec_inst)) {} | 122 : AudioEncoderOpus(CreateConfig(codec_inst), nullptr) {} |
| 114 | 123 |
| 115 AudioEncoderOpus::~AudioEncoderOpus() { | 124 AudioEncoderOpus::~AudioEncoderOpus() { |
| 116 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_)); | 125 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_)); |
| 117 } | 126 } |
| 118 | 127 |
| 119 int AudioEncoderOpus::SampleRateHz() const { | 128 int AudioEncoderOpus::SampleRateHz() const { |
| 120 return kSampleRateHz; | 129 return kSampleRateHz; |
| 121 } | 130 } |
| 122 | 131 |
| 123 size_t AudioEncoderOpus::NumChannels() const { | 132 size_t AudioEncoderOpus::NumChannels() const { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 134 | 143 |
| 135 int AudioEncoderOpus::GetTargetBitrate() const { | 144 int AudioEncoderOpus::GetTargetBitrate() const { |
| 136 return config_.GetBitrateBps(); | 145 return config_.GetBitrateBps(); |
| 137 } | 146 } |
| 138 | 147 |
| 139 void AudioEncoderOpus::Reset() { | 148 void AudioEncoderOpus::Reset() { |
| 140 RTC_CHECK(RecreateEncoderInstance(config_)); | 149 RTC_CHECK(RecreateEncoderInstance(config_)); |
| 141 } | 150 } |
| 142 | 151 |
| 143 bool AudioEncoderOpus::SetFec(bool enable) { | 152 bool AudioEncoderOpus::SetFec(bool enable) { |
| 144 auto conf = config_; | 153 if (enable) { |
| 145 conf.fec_enabled = enable; | 154 RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_)); |
| 146 return RecreateEncoderInstance(conf); | 155 } else { |
| 156 RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_)); | |
| 157 } | |
| 158 config_.fec_enabled = enable; | |
| 159 return true; | |
| 147 } | 160 } |
| 148 | 161 |
| 149 bool AudioEncoderOpus::SetDtx(bool enable) { | 162 bool AudioEncoderOpus::SetDtx(bool enable) { |
| 150 auto conf = config_; | 163 if (enable) { |
| 151 conf.dtx_enabled = enable; | 164 RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_)); |
| 152 return RecreateEncoderInstance(conf); | 165 } else { |
| 166 RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_)); | |
| 167 } | |
| 168 config_.dtx_enabled = enable; | |
| 169 return true; | |
| 153 } | 170 } |
| 154 | 171 |
| 155 bool AudioEncoderOpus::GetDtx() const { | 172 bool AudioEncoderOpus::GetDtx() const { |
| 156 return config_.dtx_enabled; | 173 return config_.dtx_enabled; |
| 157 } | 174 } |
| 158 | 175 |
| 159 bool AudioEncoderOpus::SetApplication(Application application) { | 176 bool AudioEncoderOpus::SetApplication(Application application) { |
| 160 auto conf = config_; | 177 auto conf = config_; |
| 161 switch (application) { | 178 switch (application) { |
| 162 case Application::kSpeech: | 179 case Application::kSpeech: |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 185 } | 202 } |
| 186 } | 203 } |
| 187 | 204 |
| 188 void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) { | 205 void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) { |
| 189 config_.bitrate_bps = rtc::Optional<int>( | 206 config_.bitrate_bps = rtc::Optional<int>( |
| 190 std::max(std::min(bits_per_second, kMaxBitrateBps), kMinBitrateBps)); | 207 std::max(std::min(bits_per_second, kMaxBitrateBps), kMinBitrateBps)); |
| 191 RTC_DCHECK(config_.IsOk()); | 208 RTC_DCHECK(config_.IsOk()); |
| 192 RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config_.GetBitrateBps())); | 209 RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config_.GetBitrateBps())); |
| 193 } | 210 } |
| 194 | 211 |
| 212 bool AudioEncoderOpus::EnableAudioNetworkAdaptor( | |
| 213 const std::string& config_string, | |
| 214 const Clock* clock) { | |
| 215 AudioNetworkAdaptorImpl::Config config; | |
| 216 config.clock = clock; | |
| 217 audio_network_adaptor_.reset(new AudioNetworkAdaptorImpl( | |
| 218 config, ControllerManagerImpl::Create( | |
| 219 config_string, NumChannels(), | |
| 220 rtc::ArrayView<const int>(kSupportedFrameLengths, | |
| 221 arraysize(kSupportedFrameLengths)), | |
|
kwiberg-webrtc
2016/10/03 12:48:10
1. Use the constructor that takes only an array ar
minyue-webrtc
2016/10/03 12:57:15
sure, will do.
| |
| 222 num_channels_to_encode_, next_frame_length_ms_, | |
| 223 GetTargetBitrate(), config_.fec_enabled, GetDtx(), clock))); | |
| 224 return audio_network_adaptor_.get(); | |
| 225 } | |
| 226 | |
| 227 void AudioEncoderOpus::DisableAudioNetworkAdaptor() { | |
| 228 audio_network_adaptor_.reset(nullptr); | |
| 229 } | |
| 230 | |
| 231 void AudioEncoderOpus::OnReceivedUplinkBandwidth(int uplink_bandwidth_bps) { | |
| 232 if (!audio_network_adaptor_) | |
| 233 return; | |
| 234 audio_network_adaptor_->SetUplinkBandwidth(uplink_bandwidth_bps); | |
| 235 ApplyAudioNetworkAdaptor(); | |
| 236 } | |
| 237 | |
| 238 void AudioEncoderOpus::OnReceivedUplinkPacketLossFraction( | |
| 239 float uplink_packet_loss_fraction) { | |
| 240 if (!audio_network_adaptor_) | |
| 241 return; | |
| 242 audio_network_adaptor_->SetUplinkPacketLossFraction( | |
| 243 uplink_packet_loss_fraction); | |
| 244 ApplyAudioNetworkAdaptor(); | |
| 245 } | |
| 246 | |
| 247 void AudioEncoderOpus::OnReceivedTargetAudioBitrate( | |
| 248 int target_audio_bitrate_bps) { | |
| 249 if (!audio_network_adaptor_) | |
| 250 return; | |
| 251 audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps); | |
| 252 ApplyAudioNetworkAdaptor(); | |
| 253 } | |
| 254 | |
| 255 void AudioEncoderOpus::OnReceivedRtt(int rtt_ms) { | |
| 256 if (!audio_network_adaptor_) | |
| 257 return; | |
| 258 audio_network_adaptor_->SetRtt(rtt_ms); | |
| 259 ApplyAudioNetworkAdaptor(); | |
| 260 } | |
| 261 | |
| 262 void AudioEncoderOpus::SetReceiverFrameLengthRange(int min_frame_length_ms, | |
| 263 int max_frame_length_ms) { | |
| 264 if (!audio_network_adaptor_) | |
| 265 return; | |
| 266 audio_network_adaptor_->SetReceiverFrameLengthRange(min_frame_length_ms, | |
| 267 max_frame_length_ms); | |
| 268 ApplyAudioNetworkAdaptor(); | |
| 269 } | |
| 270 | |
| 195 AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl( | 271 AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl( |
| 196 uint32_t rtp_timestamp, | 272 uint32_t rtp_timestamp, |
| 197 rtc::ArrayView<const int16_t> audio, | 273 rtc::ArrayView<const int16_t> audio, |
| 198 rtc::Buffer* encoded) { | 274 rtc::Buffer* encoded) { |
| 199 | 275 |
| 200 if (input_buffer_.empty()) | 276 if (input_buffer_.empty()) |
| 201 first_timestamp_in_buffer_ = rtp_timestamp; | 277 first_timestamp_in_buffer_ = rtp_timestamp; |
| 202 | 278 |
| 203 input_buffer_.insert(input_buffer_.end(), audio.cbegin(), audio.cend()); | 279 input_buffer_.insert(input_buffer_.end(), audio.cbegin(), audio.cend()); |
| 204 if (input_buffer_.size() < | 280 if (input_buffer_.size() < |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 219 config_.num_channels), | 295 config_.num_channels), |
| 220 rtc::saturated_cast<int16_t>(max_encoded_bytes), | 296 rtc::saturated_cast<int16_t>(max_encoded_bytes), |
| 221 encoded.data()); | 297 encoded.data()); |
| 222 | 298 |
| 223 RTC_CHECK_GE(status, 0); // Fails only if fed invalid data. | 299 RTC_CHECK_GE(status, 0); // Fails only if fed invalid data. |
| 224 | 300 |
| 225 return static_cast<size_t>(status); | 301 return static_cast<size_t>(status); |
| 226 }); | 302 }); |
| 227 input_buffer_.clear(); | 303 input_buffer_.clear(); |
| 228 | 304 |
| 305 // Will use new packet size for next encoding. | |
| 306 config_.frame_size_ms = next_frame_length_ms_; | |
| 307 | |
| 229 info.encoded_timestamp = first_timestamp_in_buffer_; | 308 info.encoded_timestamp = first_timestamp_in_buffer_; |
| 230 info.payload_type = config_.payload_type; | 309 info.payload_type = config_.payload_type; |
| 231 info.send_even_if_empty = true; // Allows Opus to send empty packets. | 310 info.send_even_if_empty = true; // Allows Opus to send empty packets. |
| 232 info.speech = (info.encoded_bytes > 0); | 311 info.speech = (info.encoded_bytes > 0); |
| 233 info.encoder_type = CodecType::kOpus; | 312 info.encoder_type = CodecType::kOpus; |
| 234 return info; | 313 return info; |
| 235 } | 314 } |
| 236 | 315 |
| 237 size_t AudioEncoderOpus::Num10msFramesPerPacket() const { | 316 size_t AudioEncoderOpus::Num10msFramesPerPacket() const { |
| 238 return static_cast<size_t>(rtc::CheckedDivExact(config_.frame_size_ms, 10)); | 317 return static_cast<size_t>(rtc::CheckedDivExact(config_.frame_size_ms, 10)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 275 RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, config.complexity)); | 354 RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, config.complexity)); |
| 276 if (config.dtx_enabled) { | 355 if (config.dtx_enabled) { |
| 277 RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_)); | 356 RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_)); |
| 278 } else { | 357 } else { |
| 279 RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_)); | 358 RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_)); |
| 280 } | 359 } |
| 281 RTC_CHECK_EQ(0, | 360 RTC_CHECK_EQ(0, |
| 282 WebRtcOpus_SetPacketLossRate( | 361 WebRtcOpus_SetPacketLossRate( |
| 283 inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5))); | 362 inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5))); |
| 284 config_ = config; | 363 config_ = config; |
| 364 | |
| 365 num_channels_to_encode_ = NumChannels(); | |
| 366 next_frame_length_ms_ = config_.frame_size_ms; | |
| 285 return true; | 367 return true; |
| 286 } | 368 } |
| 287 | 369 |
| 370 void AudioEncoderOpus::SetFrameLength(int frame_length_ms) { | |
| 371 next_frame_length_ms_ = frame_length_ms; | |
| 372 } | |
| 373 | |
| 374 void AudioEncoderOpus::SetNumChannelsToEncode(size_t num_channels_to_encode) { | |
| 375 RTC_DCHECK_GT(num_channels_to_encode, 0u); | |
| 376 RTC_DCHECK_LE(num_channels_to_encode, config_.num_channels); | |
| 377 | |
| 378 if (num_channels_to_encode_ == num_channels_to_encode) | |
| 379 return; | |
| 380 | |
| 381 RTC_CHECK_EQ(0, WebRtcOpus_SetForceChannels(inst_, num_channels_to_encode)); | |
| 382 num_channels_to_encode_ = num_channels_to_encode; | |
| 383 } | |
| 384 | |
| 385 void AudioEncoderOpus::ApplyAudioNetworkAdaptor() { | |
| 386 auto config = audio_network_adaptor_->GetEncoderRuntimeConfig(); | |
| 387 // |audio_network_adaptor_| is supposed to be configured to output all | |
| 388 // following parameters. | |
| 389 RTC_DCHECK(config.bitrate_bps); | |
| 390 RTC_DCHECK(config.frame_length_ms); | |
| 391 RTC_DCHECK(config.uplink_packet_loss_fraction); | |
| 392 RTC_DCHECK(config.enable_fec); | |
| 393 RTC_DCHECK(config.enable_dtx); | |
| 394 RTC_DCHECK(config.num_channels); | |
| 395 | |
| 396 RTC_DCHECK(*config.frame_length_ms == 20 || *config.frame_length_ms == 60); | |
| 397 | |
| 398 SetTargetBitrate(*config.bitrate_bps); | |
| 399 SetFrameLength(*config.frame_length_ms); | |
| 400 SetFec(*config.enable_fec); | |
| 401 SetProjectedPacketLossRate(*config.uplink_packet_loss_fraction); | |
| 402 SetDtx(*config.enable_dtx); | |
| 403 SetNumChannelsToEncode(*config.num_channels); | |
| 404 } | |
| 405 | |
| 288 } // namespace webrtc | 406 } // namespace webrtc |
| OLD | NEW |