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/main/acm2/codec_owner.h"
12 
13 #include "webrtc/base/checks.h"
14 #include "webrtc/base/logging.h"
15 #include "webrtc/engine_configurations.h"
16 #include "webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h"
17 #ifdef WEBRTC_CODEC_RED
18 #include "webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h"
19 #endif
20 
21 namespace webrtc {
22 namespace acm2 {
23 
CodecOwner()24 CodecOwner::CodecOwner() : speech_encoder_(nullptr) {
25 }
26 
27 CodecOwner::~CodecOwner() = default;
28 
29 namespace {
30 
CreateRedEncoder(int red_payload_type,AudioEncoder * encoder,rtc::scoped_ptr<AudioEncoder> * red_encoder)31 AudioEncoder* CreateRedEncoder(int red_payload_type,
32                                AudioEncoder* encoder,
33                                rtc::scoped_ptr<AudioEncoder>* red_encoder) {
34 #ifdef WEBRTC_CODEC_RED
35   if (red_payload_type != -1) {
36     AudioEncoderCopyRed::Config config;
37     config.payload_type = red_payload_type;
38     config.speech_encoder = encoder;
39     red_encoder->reset(new AudioEncoderCopyRed(config));
40     return red_encoder->get();
41   }
42 #endif
43 
44   red_encoder->reset();
45   return encoder;
46 }
47 
CreateCngEncoder(int cng_payload_type,ACMVADMode vad_mode,AudioEncoder * encoder,rtc::scoped_ptr<AudioEncoder> * cng_encoder)48 void CreateCngEncoder(int cng_payload_type,
49                       ACMVADMode vad_mode,
50                       AudioEncoder* encoder,
51                       rtc::scoped_ptr<AudioEncoder>* cng_encoder) {
52   if (cng_payload_type == -1) {
53     cng_encoder->reset();
54     return;
55   }
56   AudioEncoderCng::Config config;
57   config.num_channels = encoder->NumChannels();
58   config.payload_type = cng_payload_type;
59   config.speech_encoder = encoder;
60   switch (vad_mode) {
61     case VADNormal:
62       config.vad_mode = Vad::kVadNormal;
63       break;
64     case VADLowBitrate:
65       config.vad_mode = Vad::kVadLowBitrate;
66       break;
67     case VADAggr:
68       config.vad_mode = Vad::kVadAggressive;
69       break;
70     case VADVeryAggr:
71       config.vad_mode = Vad::kVadVeryAggressive;
72       break;
73     default:
74       FATAL();
75   }
76   cng_encoder->reset(new AudioEncoderCng(config));
77 }
78 }  // namespace
79 
SetEncoders(AudioEncoder * external_speech_encoder,int cng_payload_type,ACMVADMode vad_mode,int red_payload_type)80 void CodecOwner::SetEncoders(AudioEncoder* external_speech_encoder,
81                              int cng_payload_type,
82                              ACMVADMode vad_mode,
83                              int red_payload_type) {
84   speech_encoder_ = external_speech_encoder;
85   ChangeCngAndRed(cng_payload_type, vad_mode, red_payload_type);
86 }
87 
ChangeCngAndRed(int cng_payload_type,ACMVADMode vad_mode,int red_payload_type)88 void CodecOwner::ChangeCngAndRed(int cng_payload_type,
89                                  ACMVADMode vad_mode,
90                                  int red_payload_type) {
91   RTC_DCHECK(speech_encoder_);
92   if (cng_payload_type != -1 || red_payload_type != -1) {
93     // The RED and CNG encoders need to be in sync with the speech encoder, so
94     // reset the latter to ensure its buffer is empty.
95     speech_encoder_->Reset();
96   }
97   AudioEncoder* encoder = CreateRedEncoder(
98       red_payload_type, speech_encoder_, &red_encoder_);
99   CreateCngEncoder(cng_payload_type, vad_mode, encoder, &cng_encoder_);
100 }
101 
Encoder()102 AudioEncoder* CodecOwner::Encoder() {
103   const auto& const_this = *this;
104   return const_cast<AudioEncoder*>(const_this.Encoder());
105 }
106 
Encoder() const107 const AudioEncoder* CodecOwner::Encoder() const {
108   if (cng_encoder_)
109     return cng_encoder_.get();
110   if (red_encoder_)
111     return red_encoder_.get();
112   return speech_encoder_;
113 }
114 
115 }  // namespace acm2
116 }  // namespace webrtc
117