OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "webrtc/system_wrappers/include/logging.h" | 24 #include "webrtc/system_wrappers/include/logging.h" |
25 #include "webrtc/system_wrappers/include/metrics.h" | 25 #include "webrtc/system_wrappers/include/metrics.h" |
26 #include "webrtc/system_wrappers/include/rw_lock_wrapper.h" | 26 #include "webrtc/system_wrappers/include/rw_lock_wrapper.h" |
27 #include "webrtc/system_wrappers/include/trace.h" | 27 #include "webrtc/system_wrappers/include/trace.h" |
28 #include "webrtc/typedefs.h" | 28 #include "webrtc/typedefs.h" |
29 | 29 |
30 namespace webrtc { | 30 namespace webrtc { |
31 | 31 |
32 namespace acm2 { | 32 namespace acm2 { |
33 | 33 |
| 34 struct EncoderFactory { |
| 35 AudioEncoder* external_speech_encoder = nullptr; |
| 36 CodecManager codec_manager; |
| 37 RentACodec rent_a_codec; |
| 38 }; |
| 39 |
34 namespace { | 40 namespace { |
35 | 41 |
36 // TODO(turajs): the same functionality is used in NetEq. If both classes | 42 // TODO(turajs): the same functionality is used in NetEq. If both classes |
37 // need them, make it a static function in ACMCodecDB. | 43 // need them, make it a static function in ACMCodecDB. |
38 bool IsCodecRED(const CodecInst& codec) { | 44 bool IsCodecRED(const CodecInst& codec) { |
39 return (STR_CASE_CMP(codec.plname, "RED") == 0); | 45 return (STR_CASE_CMP(codec.plname, "RED") == 0); |
40 } | 46 } |
41 | 47 |
42 bool IsCodecCN(const CodecInst& codec) { | 48 bool IsCodecCN(const CodecInst& codec) { |
43 return (STR_CASE_CMP(codec.plname, "CN") == 0); | 49 return (STR_CASE_CMP(codec.plname, "CN") == 0); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 size_t offset = 0; | 89 size_t offset = 0; |
84 for (size_t i = 0; i < info.redundant.size(); ++i) { | 90 for (size_t i = 0; i < info.redundant.size(); ++i) { |
85 frag->fragmentationOffset[i] = offset; | 91 frag->fragmentationOffset[i] = offset; |
86 offset += info.redundant[i].encoded_bytes; | 92 offset += info.redundant[i].encoded_bytes; |
87 frag->fragmentationLength[i] = info.redundant[i].encoded_bytes; | 93 frag->fragmentationLength[i] = info.redundant[i].encoded_bytes; |
88 frag->fragmentationTimeDiff[i] = rtc::checked_cast<uint16_t>( | 94 frag->fragmentationTimeDiff[i] = rtc::checked_cast<uint16_t>( |
89 info.encoded_timestamp - info.redundant[i].encoded_timestamp); | 95 info.encoded_timestamp - info.redundant[i].encoded_timestamp); |
90 frag->fragmentationPlType[i] = info.redundant[i].payload_type; | 96 frag->fragmentationPlType[i] = info.redundant[i].payload_type; |
91 } | 97 } |
92 } | 98 } |
| 99 |
| 100 // Wraps a raw AudioEncoder pointer. The idea is that you can put one of these |
| 101 // in a unique_ptr, to protect the contained raw pointer from being deleted |
| 102 // when the unique_ptr expires. (This is of course a bad idea in general, but |
| 103 // backwards compatibility.) |
| 104 class RawAudioEncoderWrapper final : public AudioEncoder { |
| 105 public: |
| 106 RawAudioEncoderWrapper(AudioEncoder* enc) : enc_(enc) {} |
| 107 size_t MaxEncodedBytes() const override { return enc_->MaxEncodedBytes(); } |
| 108 int SampleRateHz() const override { return enc_->SampleRateHz(); } |
| 109 size_t NumChannels() const override { return enc_->NumChannels(); } |
| 110 int RtpTimestampRateHz() const override { return enc_->RtpTimestampRateHz(); } |
| 111 size_t Num10MsFramesInNextPacket() const override { |
| 112 return enc_->Num10MsFramesInNextPacket(); |
| 113 } |
| 114 size_t Max10MsFramesInAPacket() const override { |
| 115 return enc_->Max10MsFramesInAPacket(); |
| 116 } |
| 117 int GetTargetBitrate() const override { return enc_->GetTargetBitrate(); } |
| 118 EncodedInfo EncodeImpl(uint32_t rtp_timestamp, |
| 119 rtc::ArrayView<const int16_t> audio, |
| 120 rtc::Buffer* encoded) override { |
| 121 return enc_->Encode(rtp_timestamp, audio, encoded); |
| 122 } |
| 123 EncodedInfo EncodeInternal(uint32_t rtp_timestamp, |
| 124 rtc::ArrayView<const int16_t> audio, |
| 125 size_t max_encoded_bytes, |
| 126 uint8_t* encoded) override { |
| 127 return enc_->EncodeInternal(rtp_timestamp, audio, max_encoded_bytes, |
| 128 encoded); |
| 129 } |
| 130 void Reset() override { return enc_->Reset(); } |
| 131 bool SetFec(bool enable) override { return enc_->SetFec(enable); } |
| 132 bool SetDtx(bool enable) override { return enc_->SetDtx(enable); } |
| 133 bool SetApplication(Application application) override { |
| 134 return enc_->SetApplication(application); |
| 135 } |
| 136 void SetMaxPlaybackRate(int frequency_hz) override { |
| 137 return enc_->SetMaxPlaybackRate(frequency_hz); |
| 138 } |
| 139 void SetProjectedPacketLossRate(double fraction) override { |
| 140 return enc_->SetProjectedPacketLossRate(fraction); |
| 141 } |
| 142 void SetTargetBitrate(int target_bps) override { |
| 143 return enc_->SetTargetBitrate(target_bps); |
| 144 } |
| 145 |
| 146 private: |
| 147 AudioEncoder* enc_; |
| 148 }; |
| 149 |
| 150 // Return false on error. |
| 151 bool CreateSpeechEncoderIfNecessary(EncoderFactory* ef) { |
| 152 auto* sp = ef->codec_manager.GetStackParams(); |
| 153 if (sp->speech_encoder) { |
| 154 // Do nothing; we already have a speech encoder. |
| 155 } else if (ef->codec_manager.GetCodecInst()) { |
| 156 RTC_DCHECK(!ef->external_speech_encoder); |
| 157 // We have no speech encoder, but we have a specification for making one. |
| 158 std::unique_ptr<AudioEncoder> enc = |
| 159 ef->rent_a_codec.RentEncoder(*ef->codec_manager.GetCodecInst()); |
| 160 if (!enc) |
| 161 return false; // Encoder spec was bad. |
| 162 sp->speech_encoder = std::move(enc); |
| 163 } else if (ef->external_speech_encoder) { |
| 164 RTC_DCHECK(!ef->codec_manager.GetCodecInst()); |
| 165 // We have an external speech encoder. |
| 166 sp->speech_encoder = std::unique_ptr<AudioEncoder>( |
| 167 new RawAudioEncoderWrapper(ef->external_speech_encoder)); |
| 168 } |
| 169 return true; |
| 170 } |
| 171 |
93 } // namespace | 172 } // namespace |
94 | 173 |
95 void AudioCodingModuleImpl::ChangeLogger::MaybeLog(int value) { | 174 void AudioCodingModuleImpl::ChangeLogger::MaybeLog(int value) { |
96 if (value != last_value_ || first_time_) { | 175 if (value != last_value_ || first_time_) { |
97 first_time_ = false; | 176 first_time_ = false; |
98 last_value_ = value; | 177 last_value_ = value; |
99 RTC_HISTOGRAM_COUNTS_SPARSE_100(histogram_name_, value); | 178 RTC_HISTOGRAM_COUNTS_SPARSE_100(histogram_name_, value); |
100 } | 179 } |
101 } | 180 } |
102 | 181 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 ///////////////////////////////////////// | 272 ///////////////////////////////////////// |
194 // Sender | 273 // Sender |
195 // | 274 // |
196 | 275 |
197 // Can be called multiple times for Codec, CNG, RED. | 276 // Can be called multiple times for Codec, CNG, RED. |
198 int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) { | 277 int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) { |
199 rtc::CritScope lock(&acm_crit_sect_); | 278 rtc::CritScope lock(&acm_crit_sect_); |
200 if (!encoder_factory_->codec_manager.RegisterEncoder(send_codec)) { | 279 if (!encoder_factory_->codec_manager.RegisterEncoder(send_codec)) { |
201 return -1; | 280 return -1; |
202 } | 281 } |
| 282 if (encoder_factory_->codec_manager.GetCodecInst()) { |
| 283 encoder_factory_->external_speech_encoder = nullptr; |
| 284 } |
| 285 if (!CreateSpeechEncoderIfNecessary(encoder_factory_.get())) { |
| 286 return -1; |
| 287 } |
203 auto* sp = encoder_factory_->codec_manager.GetStackParams(); | 288 auto* sp = encoder_factory_->codec_manager.GetStackParams(); |
204 if (!sp->speech_encoder && encoder_factory_->codec_manager.GetCodecInst()) { | |
205 // We have no speech encoder, but we have a specification for making one. | |
206 AudioEncoder* enc = encoder_factory_->rent_a_codec.RentEncoder( | |
207 *encoder_factory_->codec_manager.GetCodecInst()); | |
208 if (!enc) | |
209 return -1; | |
210 sp->speech_encoder = enc; | |
211 } | |
212 if (sp->speech_encoder) | 289 if (sp->speech_encoder) |
213 encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); | 290 encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); |
214 return 0; | 291 return 0; |
215 } | 292 } |
216 | 293 |
217 void AudioCodingModuleImpl::RegisterExternalSendCodec( | 294 void AudioCodingModuleImpl::RegisterExternalSendCodec( |
218 AudioEncoder* external_speech_encoder) { | 295 AudioEncoder* external_speech_encoder) { |
219 rtc::CritScope lock(&acm_crit_sect_); | 296 rtc::CritScope lock(&acm_crit_sect_); |
| 297 encoder_factory_->codec_manager.UnsetCodecInst(); |
| 298 encoder_factory_->external_speech_encoder = external_speech_encoder; |
| 299 RTC_CHECK(CreateSpeechEncoderIfNecessary(encoder_factory_.get())); |
220 auto* sp = encoder_factory_->codec_manager.GetStackParams(); | 300 auto* sp = encoder_factory_->codec_manager.GetStackParams(); |
221 sp->speech_encoder = external_speech_encoder; | 301 RTC_CHECK(sp->speech_encoder); |
222 encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); | 302 encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); |
223 } | 303 } |
224 | 304 |
225 // Get current send codec. | 305 // Get current send codec. |
226 rtc::Optional<CodecInst> AudioCodingModuleImpl::SendCodec() const { | 306 rtc::Optional<CodecInst> AudioCodingModuleImpl::SendCodec() const { |
227 rtc::CritScope lock(&acm_crit_sect_); | 307 rtc::CritScope lock(&acm_crit_sect_); |
228 auto* ci = encoder_factory_->codec_manager.GetCodecInst(); | 308 auto* ci = encoder_factory_->codec_manager.GetCodecInst(); |
229 if (ci) { | 309 if (ci) { |
230 return rtc::Optional<CodecInst>(*ci); | 310 return rtc::Optional<CodecInst>(*ci); |
231 } | 311 } |
232 auto* enc = encoder_factory_->codec_manager.GetStackParams()->speech_encoder; | 312 CreateSpeechEncoderIfNecessary(encoder_factory_.get()); |
| 313 const std::unique_ptr<AudioEncoder>& enc = |
| 314 encoder_factory_->codec_manager.GetStackParams()->speech_encoder; |
233 if (enc) { | 315 if (enc) { |
234 return rtc::Optional<CodecInst>(CodecManager::ForgeCodecInst(enc)); | 316 return rtc::Optional<CodecInst>(CodecManager::ForgeCodecInst(enc.get())); |
235 } | 317 } |
236 return rtc::Optional<CodecInst>(); | 318 return rtc::Optional<CodecInst>(); |
237 } | 319 } |
238 | 320 |
239 // Get current send frequency. | 321 // Get current send frequency. |
240 int AudioCodingModuleImpl::SendFrequency() const { | 322 int AudioCodingModuleImpl::SendFrequency() const { |
241 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_, | 323 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_, |
242 "SendFrequency()"); | 324 "SendFrequency()"); |
243 rtc::CritScope lock(&acm_crit_sect_); | 325 rtc::CritScope lock(&acm_crit_sect_); |
244 | 326 |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 | 526 |
445 bool AudioCodingModuleImpl::REDStatus() const { | 527 bool AudioCodingModuleImpl::REDStatus() const { |
446 rtc::CritScope lock(&acm_crit_sect_); | 528 rtc::CritScope lock(&acm_crit_sect_); |
447 return encoder_factory_->codec_manager.GetStackParams()->use_red; | 529 return encoder_factory_->codec_manager.GetStackParams()->use_red; |
448 } | 530 } |
449 | 531 |
450 // Configure RED status i.e on/off. | 532 // Configure RED status i.e on/off. |
451 int AudioCodingModuleImpl::SetREDStatus(bool enable_red) { | 533 int AudioCodingModuleImpl::SetREDStatus(bool enable_red) { |
452 #ifdef WEBRTC_CODEC_RED | 534 #ifdef WEBRTC_CODEC_RED |
453 rtc::CritScope lock(&acm_crit_sect_); | 535 rtc::CritScope lock(&acm_crit_sect_); |
| 536 CreateSpeechEncoderIfNecessary(encoder_factory_.get()); |
454 if (!encoder_factory_->codec_manager.SetCopyRed(enable_red)) { | 537 if (!encoder_factory_->codec_manager.SetCopyRed(enable_red)) { |
455 return -1; | 538 return -1; |
456 } | 539 } |
457 auto* sp = encoder_factory_->codec_manager.GetStackParams(); | 540 auto* sp = encoder_factory_->codec_manager.GetStackParams(); |
458 if (sp->speech_encoder) | 541 if (sp->speech_encoder) |
459 encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); | 542 encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); |
460 return 0; | 543 return 0; |
461 #else | 544 #else |
462 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_, | 545 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_, |
463 " WEBRTC_CODEC_RED is undefined"); | 546 " WEBRTC_CODEC_RED is undefined"); |
464 return -1; | 547 return -1; |
465 #endif | 548 #endif |
466 } | 549 } |
467 | 550 |
468 ///////////////////////////////////////// | 551 ///////////////////////////////////////// |
469 // (FEC) Forward Error Correction (codec internal) | 552 // (FEC) Forward Error Correction (codec internal) |
470 // | 553 // |
471 | 554 |
472 bool AudioCodingModuleImpl::CodecFEC() const { | 555 bool AudioCodingModuleImpl::CodecFEC() const { |
473 rtc::CritScope lock(&acm_crit_sect_); | 556 rtc::CritScope lock(&acm_crit_sect_); |
474 return encoder_factory_->codec_manager.GetStackParams()->use_codec_fec; | 557 return encoder_factory_->codec_manager.GetStackParams()->use_codec_fec; |
475 } | 558 } |
476 | 559 |
477 int AudioCodingModuleImpl::SetCodecFEC(bool enable_codec_fec) { | 560 int AudioCodingModuleImpl::SetCodecFEC(bool enable_codec_fec) { |
478 rtc::CritScope lock(&acm_crit_sect_); | 561 rtc::CritScope lock(&acm_crit_sect_); |
| 562 CreateSpeechEncoderIfNecessary(encoder_factory_.get()); |
479 if (!encoder_factory_->codec_manager.SetCodecFEC(enable_codec_fec)) { | 563 if (!encoder_factory_->codec_manager.SetCodecFEC(enable_codec_fec)) { |
480 return -1; | 564 return -1; |
481 } | 565 } |
482 auto* sp = encoder_factory_->codec_manager.GetStackParams(); | 566 auto* sp = encoder_factory_->codec_manager.GetStackParams(); |
483 if (sp->speech_encoder) | 567 if (sp->speech_encoder) |
484 encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); | 568 encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); |
485 if (enable_codec_fec) { | 569 if (enable_codec_fec) { |
486 return sp->use_codec_fec ? 0 : -1; | 570 return sp->use_codec_fec ? 0 : -1; |
487 } else { | 571 } else { |
488 RTC_DCHECK(!sp->use_codec_fec); | 572 RTC_DCHECK(!sp->use_codec_fec); |
(...skipping 11 matching lines...) Expand all Loading... |
500 | 584 |
501 ///////////////////////////////////////// | 585 ///////////////////////////////////////// |
502 // (VAD) Voice Activity Detection | 586 // (VAD) Voice Activity Detection |
503 // | 587 // |
504 int AudioCodingModuleImpl::SetVAD(bool enable_dtx, | 588 int AudioCodingModuleImpl::SetVAD(bool enable_dtx, |
505 bool enable_vad, | 589 bool enable_vad, |
506 ACMVADMode mode) { | 590 ACMVADMode mode) { |
507 // Note: |enable_vad| is not used; VAD is enabled based on the DTX setting. | 591 // Note: |enable_vad| is not used; VAD is enabled based on the DTX setting. |
508 RTC_DCHECK_EQ(enable_dtx, enable_vad); | 592 RTC_DCHECK_EQ(enable_dtx, enable_vad); |
509 rtc::CritScope lock(&acm_crit_sect_); | 593 rtc::CritScope lock(&acm_crit_sect_); |
| 594 CreateSpeechEncoderIfNecessary(encoder_factory_.get()); |
510 if (!encoder_factory_->codec_manager.SetVAD(enable_dtx, mode)) { | 595 if (!encoder_factory_->codec_manager.SetVAD(enable_dtx, mode)) { |
511 return -1; | 596 return -1; |
512 } | 597 } |
513 auto* sp = encoder_factory_->codec_manager.GetStackParams(); | 598 auto* sp = encoder_factory_->codec_manager.GetStackParams(); |
514 if (sp->speech_encoder) | 599 if (sp->speech_encoder) |
515 encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); | 600 encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); |
516 return 0; | 601 return 0; |
517 } | 602 } |
518 | 603 |
519 // Get VAD/DTX settings. | 604 // Get VAD/DTX settings. |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 return receiver_.LeastRequiredDelayMs(); | 901 return receiver_.LeastRequiredDelayMs(); |
817 } | 902 } |
818 | 903 |
819 void AudioCodingModuleImpl::GetDecodingCallStatistics( | 904 void AudioCodingModuleImpl::GetDecodingCallStatistics( |
820 AudioDecodingCallStats* call_stats) const { | 905 AudioDecodingCallStats* call_stats) const { |
821 receiver_.GetDecodingCallStatistics(call_stats); | 906 receiver_.GetDecodingCallStatistics(call_stats); |
822 } | 907 } |
823 | 908 |
824 } // namespace acm2 | 909 } // namespace acm2 |
825 } // namespace webrtc | 910 } // namespace webrtc |
OLD | NEW |