LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/audio_coding/acm2 - codec_manager.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 108 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
       3             :  *
       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
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/modules/audio_coding/acm2/codec_manager.h"
      12             : 
      13             : #include "webrtc/base/checks.h"
      14             : #include "webrtc/base/format_macros.h"
      15             : #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
      16             : #include "webrtc/system_wrappers/include/trace.h"
      17             : #include "webrtc/typedefs.h"
      18             : 
      19             : namespace webrtc {
      20             : namespace acm2 {
      21             : 
      22             : namespace {
      23             : 
      24             : // Check if the given codec is a valid to be registered as send codec.
      25           0 : int IsValidSendCodec(const CodecInst& send_codec) {
      26           0 :   int dummy_id = 0;
      27           0 :   if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
      28             :     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
      29             :                  "Wrong number of channels (%" PRIuS ", only mono and stereo "
      30             :                  "are supported)",
      31             :                  send_codec.channels);
      32           0 :     return -1;
      33             :   }
      34             : 
      35           0 :   auto maybe_codec_id = RentACodec::CodecIdByInst(send_codec);
      36           0 :   if (!maybe_codec_id) {
      37             :     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
      38             :                  "Invalid codec setting for the send codec.");
      39           0 :     return -1;
      40             :   }
      41             : 
      42             :   // Telephone-event cannot be a send codec.
      43           0 :   if (!STR_CASE_CMP(send_codec.plname, "telephone-event")) {
      44             :     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
      45             :                  "telephone-event cannot be a send codec");
      46           0 :     return -1;
      47             :   }
      48             : 
      49           0 :   if (!RentACodec::IsSupportedNumChannels(*maybe_codec_id, send_codec.channels)
      50           0 :            .value_or(false)) {
      51             :     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
      52             :                  "%" PRIuS " number of channels not supportedn for %s.",
      53             :                  send_codec.channels, send_codec.plname);
      54           0 :     return -1;
      55             :   }
      56           0 :   return RentACodec::CodecIndexFromId(*maybe_codec_id).value_or(-1);
      57             : }
      58             : 
      59           0 : bool IsOpus(const CodecInst& codec) {
      60             :   return
      61             : #ifdef WEBRTC_CODEC_OPUS
      62           0 :       !STR_CASE_CMP(codec.plname, "opus") ||
      63             : #endif
      64           0 :       false;
      65             : }
      66             : 
      67             : }  // namespace
      68             : 
      69           0 : CodecManager::CodecManager() {
      70           0 :   thread_checker_.DetachFromThread();
      71           0 : }
      72             : 
      73             : CodecManager::~CodecManager() = default;
      74             : 
      75           0 : bool CodecManager::RegisterEncoder(const CodecInst& send_codec) {
      76           0 :   RTC_DCHECK(thread_checker_.CalledOnValidThread());
      77           0 :   int codec_id = IsValidSendCodec(send_codec);
      78             : 
      79             :   // Check for reported errors from function IsValidSendCodec().
      80           0 :   if (codec_id < 0) {
      81           0 :     return false;
      82             :   }
      83             : 
      84           0 :   int dummy_id = 0;
      85           0 :   switch (RentACodec::RegisterRedPayloadType(
      86             :       &codec_stack_params_.red_payload_types, send_codec)) {
      87             :     case RentACodec::RegistrationResult::kOk:
      88           0 :       return true;
      89             :     case RentACodec::RegistrationResult::kBadFreq:
      90             :       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
      91             :                    "RegisterSendCodec() failed, invalid frequency for RED"
      92             :                    " registration");
      93           0 :       return false;
      94             :     case RentACodec::RegistrationResult::kSkip:
      95           0 :       break;
      96             :   }
      97           0 :   switch (RentACodec::RegisterCngPayloadType(
      98             :       &codec_stack_params_.cng_payload_types, send_codec)) {
      99             :     case RentACodec::RegistrationResult::kOk:
     100           0 :       return true;
     101             :     case RentACodec::RegistrationResult::kBadFreq:
     102             :       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
     103             :                    "RegisterSendCodec() failed, invalid frequency for CNG"
     104             :                    " registration");
     105           0 :       return false;
     106             :     case RentACodec::RegistrationResult::kSkip:
     107           0 :       break;
     108             :   }
     109             : 
     110           0 :   if (IsOpus(send_codec)) {
     111             :     // VAD/DTX not supported.
     112           0 :     codec_stack_params_.use_cng = false;
     113             :   }
     114             : 
     115           0 :   send_codec_inst_ = rtc::Optional<CodecInst>(send_codec);
     116           0 :   recreate_encoder_ = true;  // Caller must recreate it.
     117           0 :   return true;
     118             : }
     119             : 
     120           0 : CodecInst CodecManager::ForgeCodecInst(
     121             :     const AudioEncoder* external_speech_encoder) {
     122             :   CodecInst ci;
     123           0 :   ci.channels = external_speech_encoder->NumChannels();
     124           0 :   ci.plfreq = external_speech_encoder->SampleRateHz();
     125           0 :   ci.pacsize = rtc::CheckedDivExact(
     126           0 :       static_cast<int>(external_speech_encoder->Max10MsFramesInAPacket() *
     127           0 :                        ci.plfreq),
     128             :       100);
     129           0 :   ci.pltype = -1;  // Not valid.
     130           0 :   ci.rate = -1;    // Not valid.
     131             :   static const char kName[] = "external";
     132           0 :   memcpy(ci.plname, kName, sizeof(kName));
     133           0 :   return ci;
     134             : }
     135             : 
     136           0 : bool CodecManager::SetCopyRed(bool enable) {
     137           0 :   if (enable && codec_stack_params_.use_codec_fec) {
     138             :     WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
     139             :                  "Codec internal FEC and RED cannot be co-enabled.");
     140           0 :     return false;
     141             :   }
     142           0 :   if (enable && send_codec_inst_ &&
     143           0 :       codec_stack_params_.red_payload_types.count(send_codec_inst_->plfreq) <
     144             :           1) {
     145             :     WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
     146             :                  "Cannot enable RED at %i Hz.", send_codec_inst_->plfreq);
     147           0 :     return false;
     148             :   }
     149           0 :   codec_stack_params_.use_red = enable;
     150           0 :   return true;
     151             : }
     152             : 
     153           0 : bool CodecManager::SetVAD(bool enable, ACMVADMode mode) {
     154             :   // Sanity check of the mode.
     155           0 :   RTC_DCHECK(mode == VADNormal || mode == VADLowBitrate || mode == VADAggr ||
     156           0 :              mode == VADVeryAggr);
     157             : 
     158             :   // Check that the send codec is mono. We don't support VAD/DTX for stereo
     159             :   // sending.
     160             :   const bool stereo_send =
     161             :       codec_stack_params_.speech_encoder
     162           0 :           ? (codec_stack_params_.speech_encoder->NumChannels() != 1)
     163           0 :           : false;
     164           0 :   if (enable && stereo_send) {
     165             :     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
     166             :                  "VAD/DTX not supported for stereo sending");
     167           0 :     return false;
     168             :   }
     169             : 
     170             :   // TODO(kwiberg): This doesn't protect Opus when injected as an external
     171             :   // encoder.
     172           0 :   if (send_codec_inst_ && IsOpus(*send_codec_inst_)) {
     173             :     // VAD/DTX not supported, but don't fail.
     174           0 :     enable = false;
     175             :   }
     176             : 
     177           0 :   codec_stack_params_.use_cng = enable;
     178           0 :   codec_stack_params_.vad_mode = mode;
     179           0 :   return true;
     180             : }
     181             : 
     182           0 : bool CodecManager::SetCodecFEC(bool enable_codec_fec) {
     183           0 :   if (enable_codec_fec && codec_stack_params_.use_red) {
     184             :     WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
     185             :                  "Codec internal FEC and RED cannot be co-enabled.");
     186           0 :     return false;
     187             :   }
     188             : 
     189           0 :   codec_stack_params_.use_codec_fec = enable_codec_fec;
     190           0 :   return true;
     191             : }
     192             : 
     193           0 : bool CodecManager::MakeEncoder(RentACodec* rac, AudioCodingModule* acm) {
     194           0 :   RTC_DCHECK(rac);
     195           0 :   RTC_DCHECK(acm);
     196             : 
     197           0 :   if (!recreate_encoder_) {
     198           0 :     bool error = false;
     199             :     // Try to re-use the speech encoder we've given to the ACM.
     200           0 :     acm->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
     201           0 :       if (!*encoder) {
     202             :         // There is no existing encoder.
     203           0 :         recreate_encoder_ = true;
     204           0 :         return;
     205             :       }
     206             : 
     207             :       // Extract the speech encoder from the ACM.
     208           0 :       std::unique_ptr<AudioEncoder> enc = std::move(*encoder);
     209             :       while (true) {
     210           0 :         auto sub_enc = enc->ReclaimContainedEncoders();
     211           0 :         if (sub_enc.empty()) {
     212           0 :           break;
     213             :         }
     214           0 :         RTC_CHECK_EQ(1, sub_enc.size());
     215             : 
     216             :         // Replace enc with its sub encoder. We need to put the sub encoder in
     217             :         // a temporary first, since otherwise the old value of enc would be
     218             :         // destroyed before the new value got assigned, which would be bad
     219             :         // since the new value is a part of the old value.
     220           0 :         auto tmp_enc = std::move(sub_enc[0]);
     221           0 :         enc = std::move(tmp_enc);
     222           0 :       }
     223             : 
     224             :       // Wrap it in a new encoder stack and put it back.
     225           0 :       codec_stack_params_.speech_encoder = std::move(enc);
     226           0 :       *encoder = rac->RentEncoderStack(&codec_stack_params_);
     227           0 :       if (!*encoder) {
     228           0 :         error = true;
     229             :       }
     230           0 :     });
     231           0 :     if (error) {
     232           0 :       return false;
     233             :     }
     234           0 :     if (!recreate_encoder_) {
     235           0 :       return true;
     236             :     }
     237             :   }
     238             : 
     239           0 :   if (!send_codec_inst_) {
     240             :     // We don't have the information we need to create a new speech encoder.
     241             :     // (This is not an error.)
     242           0 :     return true;
     243             :   }
     244             : 
     245           0 :   codec_stack_params_.speech_encoder = rac->RentEncoder(*send_codec_inst_);
     246           0 :   auto stack = rac->RentEncoderStack(&codec_stack_params_);
     247           0 :   if (!stack) {
     248           0 :     return false;
     249             :   }
     250           0 :   acm->SetEncoder(std::move(stack));
     251           0 :   recreate_encoder_ = false;
     252           0 :   return true;
     253             : }
     254             : 
     255             : }  // namespace acm2
     256             : }  // namespace webrtc

Generated by: LCOV version 1.13