Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: webrtc/modules/audio_coding/main/acm2/codec_manager.cc

Issue 1481493004: audio_coding: remove "main" directory (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebased Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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_manager.h"
12
13 #include "webrtc/base/checks.h"
14 #include "webrtc/engine_configurations.h"
15 #include "webrtc/modules/audio_coding/main/acm2/rent_a_codec.h"
16 #include "webrtc/system_wrappers/include/trace.h"
17
18 namespace webrtc {
19 namespace acm2 {
20
21 namespace {
22
23 // Check if the given codec is a valid to be registered as send codec.
24 int IsValidSendCodec(const CodecInst& send_codec) {
25 int dummy_id = 0;
26 if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
27 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
28 "Wrong number of channels (%d, only mono and stereo are "
29 "supported)",
30 send_codec.channels);
31 return -1;
32 }
33
34 auto maybe_codec_id = RentACodec::CodecIdByInst(send_codec);
35 if (!maybe_codec_id) {
36 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
37 "Invalid codec setting for the send codec.");
38 return -1;
39 }
40
41 // Telephone-event cannot be a send codec.
42 if (!STR_CASE_CMP(send_codec.plname, "telephone-event")) {
43 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
44 "telephone-event cannot be a send codec");
45 return -1;
46 }
47
48 if (!RentACodec::IsSupportedNumChannels(*maybe_codec_id, send_codec.channels)
49 .value_or(false)) {
50 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
51 "%d number of channels not supportedn for %s.",
52 send_codec.channels, send_codec.plname);
53 return -1;
54 }
55 return RentACodec::CodecIndexFromId(*maybe_codec_id).value_or(-1);
56 }
57
58 bool IsIsac(const CodecInst& codec) {
59 return
60 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
61 !STR_CASE_CMP(codec.plname, "isac") ||
62 #endif
63 false;
64 }
65
66 bool IsOpus(const CodecInst& codec) {
67 return
68 #ifdef WEBRTC_CODEC_OPUS
69 !STR_CASE_CMP(codec.plname, "opus") ||
70 #endif
71 false;
72 }
73
74 bool IsPcmU(const CodecInst& codec) {
75 return !STR_CASE_CMP(codec.plname, "pcmu");
76 }
77
78 bool IsPcmA(const CodecInst& codec) {
79 return !STR_CASE_CMP(codec.plname, "pcma");
80 }
81
82 bool IsPcm16B(const CodecInst& codec) {
83 return !STR_CASE_CMP(codec.plname, "l16");
84 }
85
86 bool IsIlbc(const CodecInst& codec) {
87 return
88 #ifdef WEBRTC_CODEC_ILBC
89 !STR_CASE_CMP(codec.plname, "ilbc") ||
90 #endif
91 false;
92 }
93
94 bool IsG722(const CodecInst& codec) {
95 return
96 #ifdef WEBRTC_CODEC_G722
97 !STR_CASE_CMP(codec.plname, "g722") ||
98 #endif
99 false;
100 }
101
102 bool CodecSupported(const CodecInst& codec) {
103 return IsOpus(codec) || IsPcmU(codec) || IsPcmA(codec) || IsPcm16B(codec) ||
104 IsIlbc(codec) || IsG722(codec) || IsIsac(codec);
105 }
106
107 const CodecInst kEmptyCodecInst = {-1, "noCodecRegistered", 0, 0, 0, 0};
108 } // namespace
109
110 CodecManager::CodecManager()
111 : send_codec_inst_(kEmptyCodecInst), encoder_is_opus_(false) {
112 thread_checker_.DetachFromThread();
113 }
114
115 CodecManager::~CodecManager() = default;
116
117 int CodecManager::RegisterEncoder(const CodecInst& send_codec) {
118 RTC_DCHECK(thread_checker_.CalledOnValidThread());
119 int codec_id = IsValidSendCodec(send_codec);
120
121 // Check for reported errors from function IsValidSendCodec().
122 if (codec_id < 0) {
123 return -1;
124 }
125
126 int dummy_id = 0;
127 switch (RentACodec::RegisterRedPayloadType(
128 &codec_stack_params_.red_payload_types, send_codec)) {
129 case RentACodec::RegistrationResult::kOk:
130 return 0;
131 case RentACodec::RegistrationResult::kBadFreq:
132 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
133 "RegisterSendCodec() failed, invalid frequency for RED"
134 " registration");
135 return -1;
136 case RentACodec::RegistrationResult::kSkip:
137 break;
138 }
139 switch (RentACodec::RegisterCngPayloadType(
140 &codec_stack_params_.cng_payload_types, send_codec)) {
141 case RentACodec::RegistrationResult::kOk:
142 return 0;
143 case RentACodec::RegistrationResult::kBadFreq:
144 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
145 "RegisterSendCodec() failed, invalid frequency for CNG"
146 " registration");
147 return -1;
148 case RentACodec::RegistrationResult::kSkip:
149 break;
150 }
151
152 // Check if the codec is already registered as send codec.
153 bool new_codec = true;
154 if (CurrentEncoder()) {
155 auto new_codec_id = RentACodec::CodecIdByInst(send_codec_inst_);
156 RTC_DCHECK(new_codec_id);
157 auto old_codec_id = RentACodec::CodecIdFromIndex(codec_id);
158 new_codec = !old_codec_id || *new_codec_id != *old_codec_id;
159 }
160
161 encoder_is_opus_ = IsOpus(send_codec);
162
163 if (new_codec) {
164 // This is a new codec. Register it and return.
165 RTC_DCHECK(CodecSupported(send_codec));
166 if (IsOpus(send_codec)) {
167 // VAD/DTX not supported.
168 codec_stack_params_.use_cng = false;
169 }
170 AudioEncoder* enc = rent_a_codec_.RentEncoder(send_codec);
171 if (!enc)
172 return -1;
173 rent_a_codec_.RentEncoderStack(enc, &codec_stack_params_);
174 RTC_DCHECK(CurrentEncoder());
175
176 send_codec_inst_ = send_codec;
177 return 0;
178 }
179
180 // This is an existing codec; re-create it if any parameters have changed.
181 if (send_codec_inst_.plfreq != send_codec.plfreq ||
182 send_codec_inst_.pacsize != send_codec.pacsize ||
183 send_codec_inst_.channels != send_codec.channels) {
184 AudioEncoder* enc = rent_a_codec_.RentEncoder(send_codec);
185 if (!enc)
186 return -1;
187 rent_a_codec_.RentEncoderStack(enc, &codec_stack_params_);
188 RTC_DCHECK(CurrentEncoder());
189 }
190 send_codec_inst_.plfreq = send_codec.plfreq;
191 send_codec_inst_.pacsize = send_codec.pacsize;
192 send_codec_inst_.channels = send_codec.channels;
193 send_codec_inst_.pltype = send_codec.pltype;
194
195 // Check if a change in Rate is required.
196 if (send_codec.rate != send_codec_inst_.rate) {
197 CurrentEncoder()->SetTargetBitrate(send_codec.rate);
198 send_codec_inst_.rate = send_codec.rate;
199 }
200
201 return 0;
202 }
203
204 void CodecManager::RegisterEncoder(AudioEncoder* external_speech_encoder) {
205 // Make up a CodecInst.
206 send_codec_inst_.channels = external_speech_encoder->NumChannels();
207 send_codec_inst_.plfreq = external_speech_encoder->SampleRateHz();
208 send_codec_inst_.pacsize = rtc::CheckedDivExact(
209 static_cast<int>(external_speech_encoder->Max10MsFramesInAPacket() *
210 send_codec_inst_.plfreq),
211 100);
212 send_codec_inst_.pltype = -1; // Not valid.
213 send_codec_inst_.rate = -1; // Not valid.
214 static const char kName[] = "external";
215 memcpy(send_codec_inst_.plname, kName, sizeof(kName));
216
217 rent_a_codec_.RentEncoderStack(external_speech_encoder, &codec_stack_params_);
218 }
219
220 rtc::Optional<CodecInst> CodecManager::GetCodecInst() const {
221 int dummy_id = 0;
222 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, dummy_id,
223 "SendCodec()");
224
225 if (!CurrentEncoder()) {
226 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, dummy_id,
227 "SendCodec Failed, no codec is registered");
228 return rtc::Optional<CodecInst>();
229 }
230 return rtc::Optional<CodecInst>(send_codec_inst_);
231 }
232
233 bool CodecManager::SetCopyRed(bool enable) {
234 if (enable && codec_stack_params_.use_codec_fec) {
235 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
236 "Codec internal FEC and RED cannot be co-enabled.");
237 return false;
238 }
239 if (enable &&
240 codec_stack_params_.red_payload_types.count(send_codec_inst_.plfreq) <
241 1) {
242 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
243 "Cannot enable RED at %i Hz.", send_codec_inst_.plfreq);
244 return false;
245 }
246 if (codec_stack_params_.use_red != enable) {
247 codec_stack_params_.use_red = enable;
248 if (CurrentEncoder())
249 rent_a_codec_.RentEncoderStack(rent_a_codec_.GetEncoder(),
250 &codec_stack_params_);
251 }
252 return true;
253 }
254
255 int CodecManager::SetVAD(bool enable, ACMVADMode mode) {
256 // Sanity check of the mode.
257 RTC_DCHECK(mode == VADNormal || mode == VADLowBitrate || mode == VADAggr ||
258 mode == VADVeryAggr);
259
260 // Check that the send codec is mono. We don't support VAD/DTX for stereo
261 // sending.
262 auto* enc = rent_a_codec_.GetEncoder();
263 const bool stereo_send = enc ? (enc->NumChannels() != 1) : false;
264 if (enable && stereo_send) {
265 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
266 "VAD/DTX not supported for stereo sending");
267 codec_stack_params_.use_cng = false;
268 return -1;
269 }
270
271 // If a send codec is registered, set VAD/DTX for the codec.
272 if (IsOpus(send_codec_inst_)) {
273 // VAD/DTX not supported.
274 codec_stack_params_.use_cng = false;
275 return 0;
276 }
277
278 if (codec_stack_params_.use_cng != enable ||
279 codec_stack_params_.vad_mode != mode) {
280 codec_stack_params_.use_cng = enable;
281 codec_stack_params_.vad_mode = mode;
282 if (enc)
283 rent_a_codec_.RentEncoderStack(enc, &codec_stack_params_);
284 }
285 return 0;
286 }
287
288 void CodecManager::VAD(bool* dtx_enabled,
289 bool* vad_enabled,
290 ACMVADMode* mode) const {
291 *dtx_enabled = *vad_enabled = codec_stack_params_.use_cng;
292 *mode = codec_stack_params_.vad_mode;
293 }
294
295 int CodecManager::SetCodecFEC(bool enable_codec_fec) {
296 if (enable_codec_fec && codec_stack_params_.use_red) {
297 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
298 "Codec internal FEC and RED cannot be co-enabled.");
299 return -1;
300 }
301
302 RTC_CHECK(CurrentEncoder());
303 codec_stack_params_.use_codec_fec =
304 CurrentEncoder()->SetFec(enable_codec_fec) && enable_codec_fec;
305 return codec_stack_params_.use_codec_fec == enable_codec_fec ? 0 : -1;
306 }
307
308 AudioDecoder* CodecManager::GetAudioDecoder(const CodecInst& codec) {
309 return IsIsac(codec) ? rent_a_codec_.RentIsacDecoder() : nullptr;
310 }
311
312 } // namespace acm2
313 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_coding/main/acm2/codec_manager.h ('k') | webrtc/modules/audio_coding/main/acm2/codec_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698