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