blob: 7b9c7ed5a949db37b8dbd842a1389fd99efbf479 [file] [log] [blame]
Henrik Lundin046319e2015-03-30 17:00:441/*
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"
Karl Wiberg5168ae62015-05-18 10:18:5414#include "webrtc/engine_configurations.h"
15#include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
Karl Wiberg6d216ed2015-05-07 13:49:2316#include "webrtc/system_wrappers/interface/trace.h"
Henrik Lundin046319e2015-03-30 17:00:4417
18namespace webrtc {
19namespace acm2 {
20
21namespace {
Karl Wiberg6d216ed2015-05-07 13:49:2322bool IsCodecRED(const CodecInst& codec) {
23 return (STR_CASE_CMP(codec.plname, "RED") == 0);
Henrik Lundin046319e2015-03-30 17:00:4424}
25
26bool IsCodecRED(int index) {
Karl Wiberg6d216ed2015-05-07 13:49:2327 return (IsCodecRED(ACMCodecDB::database_[index]));
Henrik Lundin046319e2015-03-30 17:00:4428}
29
Karl Wiberg6d216ed2015-05-07 13:49:2330bool IsCodecCN(const CodecInst& codec) {
31 return (STR_CASE_CMP(codec.plname, "CN") == 0);
Henrik Lundin046319e2015-03-30 17:00:4432}
33
34bool IsCodecCN(int index) {
Karl Wiberg6d216ed2015-05-07 13:49:2335 return (IsCodecCN(ACMCodecDB::database_[index]));
Henrik Lundin046319e2015-03-30 17:00:4436}
37
38// Check if the given codec is a valid to be registered as send codec.
Henrik Lundindc044342015-04-13 07:31:1639int IsValidSendCodec(const CodecInst& send_codec, bool is_primary_encoder) {
Henrik Lundin046319e2015-03-30 17:00:4440 int dummy_id = 0;
41 if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
42 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
43 "Wrong number of channels (%d, only mono and stereo are "
44 "supported) for %s encoder",
45 send_codec.channels,
46 is_primary_encoder ? "primary" : "secondary");
47 return -1;
48 }
49
Henrik Lundindc044342015-04-13 07:31:1650 int codec_id = ACMCodecDB::CodecNumber(send_codec);
Henrik Lundin046319e2015-03-30 17:00:4451 if (codec_id < 0) {
52 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
53 "Invalid codec setting for the send codec.");
54 return -1;
55 }
56
57 // TODO(tlegrand): Remove this check. Already taken care of in
58 // ACMCodecDB::CodecNumber().
59 // Check if the payload-type is valid
60 if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
61 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
62 "Invalid payload-type %d for %s.", send_codec.pltype,
63 send_codec.plname);
64 return -1;
65 }
66
67 // Telephone-event cannot be a send codec.
68 if (!STR_CASE_CMP(send_codec.plname, "telephone-event")) {
69 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
70 "telephone-event cannot be a send codec");
Henrik Lundin046319e2015-03-30 17:00:4471 return -1;
72 }
73
74 if (ACMCodecDB::codec_settings_[codec_id].channel_support <
75 send_codec.channels) {
76 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
77 "%d number of channels not supportedn for %s.",
78 send_codec.channels, send_codec.plname);
Henrik Lundin046319e2015-03-30 17:00:4479 return -1;
80 }
81
82 if (!is_primary_encoder) {
83 // If registering the secondary encoder, then RED and CN are not valid
84 // choices as encoder.
Karl Wiberg6d216ed2015-05-07 13:49:2385 if (IsCodecRED(send_codec)) {
Henrik Lundin046319e2015-03-30 17:00:4486 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
87 "RED cannot be secondary codec");
Henrik Lundin046319e2015-03-30 17:00:4488 return -1;
89 }
90
Karl Wiberg6d216ed2015-05-07 13:49:2391 if (IsCodecCN(send_codec)) {
Henrik Lundin046319e2015-03-30 17:00:4492 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
93 "DTX cannot be secondary codec");
Henrik Lundin046319e2015-03-30 17:00:4494 return -1;
95 }
96 }
97 return codec_id;
98}
99
Henrik Lundindc044342015-04-13 07:31:16100bool IsIsac(const CodecInst& codec) {
Karl Wiberg6d216ed2015-05-07 13:49:23101 return
102#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
103 !STR_CASE_CMP(codec.plname, "isac") ||
104#endif
105 false;
106}
107
108bool IsOpus(const CodecInst& codec) {
109 return
110#ifdef WEBRTC_CODEC_OPUS
111 !STR_CASE_CMP(codec.plname, "opus") ||
112#endif
113 false;
114}
115
116bool IsPcmU(const CodecInst& codec) {
117 return !STR_CASE_CMP(codec.plname, "pcmu");
118}
119
120bool IsPcmA(const CodecInst& codec) {
121 return !STR_CASE_CMP(codec.plname, "pcma");
122}
123
124bool IsPcm16B(const CodecInst& codec) {
125 return
126#ifdef WEBRTC_CODEC_PCM16
127 !STR_CASE_CMP(codec.plname, "l16") ||
128#endif
129 false;
130}
131
132bool IsIlbc(const CodecInst& codec) {
133 return
134#ifdef WEBRTC_CODEC_ILBC
135 !STR_CASE_CMP(codec.plname, "ilbc") ||
136#endif
137 false;
138}
139
140bool IsG722(const CodecInst& codec) {
141 return
142#ifdef WEBRTC_CODEC_G722
143 !STR_CASE_CMP(codec.plname, "g722") ||
144#endif
145 false;
146}
147
148bool CodecSupported(const CodecInst& codec) {
149 return IsOpus(codec) || IsPcmU(codec) || IsPcmA(codec) || IsPcm16B(codec) ||
150 IsIlbc(codec) || IsG722(codec) || IsIsac(codec);
Henrik Lundindc044342015-04-13 07:31:16151}
152
Henrik Lundin046319e2015-03-30 17:00:44153const CodecInst kEmptyCodecInst = {-1, "noCodecRegistered", 0, 0, 0, 0};
154} // namespace
155
Karl Wiberg5168ae62015-05-18 10:18:54156CodecManager::CodecManager()
157 : cng_nb_pltype_(255),
Henrik Lundin046319e2015-03-30 17:00:44158 cng_wb_pltype_(255),
159 cng_swb_pltype_(255),
160 cng_fb_pltype_(255),
161 red_nb_pltype_(255),
162 stereo_send_(false),
Henrik Lundin046319e2015-03-30 17:00:44163 dtx_enabled_(false),
164 vad_mode_(VADNormal),
Henrik Lundin046319e2015-03-30 17:00:44165 send_codec_inst_(kEmptyCodecInst),
166 red_enabled_(false),
167 codec_fec_enabled_(false) {
Henrik Lundin046319e2015-03-30 17:00:44168 // Register the default payload type for RED and for CNG at sampling rates of
169 // 8, 16, 32 and 48 kHz.
170 for (int i = (ACMCodecDB::kNumCodecs - 1); i >= 0; i--) {
171 if (IsCodecRED(i) && ACMCodecDB::database_[i].plfreq == 8000) {
172 red_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
173 } else if (IsCodecCN(i)) {
174 if (ACMCodecDB::database_[i].plfreq == 8000) {
175 cng_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
176 } else if (ACMCodecDB::database_[i].plfreq == 16000) {
177 cng_wb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
178 } else if (ACMCodecDB::database_[i].plfreq == 32000) {
179 cng_swb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
180 } else if (ACMCodecDB::database_[i].plfreq == 48000) {
181 cng_fb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
182 }
183 }
184 }
185 thread_checker_.DetachFromThread();
186}
187
Henrik Lundindc044342015-04-13 07:31:16188CodecManager::~CodecManager() = default;
Henrik Lundin046319e2015-03-30 17:00:44189
Karl Wiberg48a57c62015-05-18 12:52:29190int CodecManager::RegisterEncoder(const CodecInst& send_codec) {
Henrik Lundin046319e2015-03-30 17:00:44191 DCHECK(thread_checker_.CalledOnValidThread());
Henrik Lundindc044342015-04-13 07:31:16192 int codec_id = IsValidSendCodec(send_codec, true);
Henrik Lundin046319e2015-03-30 17:00:44193
194 // Check for reported errors from function IsValidSendCodec().
195 if (codec_id < 0) {
196 return -1;
197 }
198
199 int dummy_id = 0;
200 // RED can be registered with other payload type. If not registered a default
201 // payload type is used.
Karl Wiberg6d216ed2015-05-07 13:49:23202 if (IsCodecRED(send_codec)) {
Henrik Lundin046319e2015-03-30 17:00:44203 // TODO(tlegrand): Remove this check. Already taken care of in
204 // ACMCodecDB::CodecNumber().
205 // Check if the payload-type is valid
206 if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
207 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
208 "Invalid payload-type %d for %s.", send_codec.pltype,
209 send_codec.plname);
210 return -1;
211 }
212 // Set RED payload type.
213 if (send_codec.plfreq == 8000) {
214 red_nb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
215 } else {
216 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
217 "RegisterSendCodec() failed, invalid frequency for RED "
218 "registration");
219 return -1;
220 }
Henrik Lundin046319e2015-03-30 17:00:44221 return 0;
222 }
223
224 // CNG can be registered with other payload type. If not registered the
225 // default payload types from codec database will be used.
Karl Wiberg6d216ed2015-05-07 13:49:23226 if (IsCodecCN(send_codec)) {
Henrik Lundin046319e2015-03-30 17:00:44227 // CNG is registered.
228 switch (send_codec.plfreq) {
229 case 8000: {
230 cng_nb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
Karl Wiberg6d216ed2015-05-07 13:49:23231 return 0;
Henrik Lundin046319e2015-03-30 17:00:44232 }
233 case 16000: {
234 cng_wb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
Karl Wiberg6d216ed2015-05-07 13:49:23235 return 0;
Henrik Lundin046319e2015-03-30 17:00:44236 }
237 case 32000: {
238 cng_swb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
Karl Wiberg6d216ed2015-05-07 13:49:23239 return 0;
Henrik Lundin046319e2015-03-30 17:00:44240 }
241 case 48000: {
242 cng_fb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
Karl Wiberg6d216ed2015-05-07 13:49:23243 return 0;
Henrik Lundin046319e2015-03-30 17:00:44244 }
245 default: {
246 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
247 "RegisterSendCodec() failed, invalid frequency for CNG "
248 "registration");
249 return -1;
250 }
251 }
Henrik Lundin046319e2015-03-30 17:00:44252 }
253
254 // Set Stereo, and make sure VAD and DTX is turned off.
255 if (send_codec.channels == 2) {
256 stereo_send_ = true;
Karl Wiberg6d216ed2015-05-07 13:49:23257 if (dtx_enabled_) {
Henrik Lundin046319e2015-03-30 17:00:44258 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, dummy_id,
259 "VAD/DTX is turned off, not supported when sending stereo.");
260 }
Henrik Lundin046319e2015-03-30 17:00:44261 dtx_enabled_ = false;
262 } else {
263 stereo_send_ = false;
264 }
265
266 // Check if the codec is already registered as send codec.
Karl Wiberg6d216ed2015-05-07 13:49:23267 bool new_codec = true;
268 if (codec_owner_.Encoder()) {
269 int new_codec_id = ACMCodecDB::CodecNumber(send_codec_inst_);
270 DCHECK_GE(new_codec_id, 0);
271 new_codec = new_codec_id != codec_id;
Henrik Lundin046319e2015-03-30 17:00:44272 }
273
Karl Wiberg6d216ed2015-05-07 13:49:23274 if (RedPayloadType(send_codec.plfreq) == -1) {
275 red_enabled_ = false;
276 }
277
278 if (new_codec) {
279 // This is a new codec. Register it and return.
280 DCHECK(CodecSupported(send_codec));
281 if (IsOpus(send_codec)) {
282 // VAD/DTX not supported.
283 dtx_enabled_ = false;
Henrik Lundin046319e2015-03-30 17:00:44284 }
Karl Wiberg6d216ed2015-05-07 13:49:23285 codec_owner_.SetEncoders(
286 send_codec, dtx_enabled_ ? CngPayloadType(send_codec.plfreq) : -1,
287 vad_mode_, red_enabled_ ? RedPayloadType(send_codec.plfreq) : -1);
288 DCHECK(codec_owner_.Encoder());
Henrik Lundin046319e2015-03-30 17:00:44289
Karl Wiberg6d216ed2015-05-07 13:49:23290 codec_fec_enabled_ =
291 codec_fec_enabled_ &&
292 codec_owner_.SpeechEncoder()->SetFec(codec_fec_enabled_);
Henrik Lundin046319e2015-03-30 17:00:44293
Karl Wiberg6d216ed2015-05-07 13:49:23294 send_codec_inst_ = send_codec;
Henrik Lundin046319e2015-03-30 17:00:44295 return 0;
296 }
Karl Wiberg6d216ed2015-05-07 13:49:23297
298 // This is an existing codec; re-create it if any parameters have changed.
299 if (send_codec_inst_.plfreq != send_codec.plfreq ||
300 send_codec_inst_.pacsize != send_codec.pacsize ||
301 send_codec_inst_.channels != send_codec.channels) {
302 codec_owner_.SetEncoders(
303 send_codec, dtx_enabled_ ? CngPayloadType(send_codec.plfreq) : -1,
304 vad_mode_, red_enabled_ ? RedPayloadType(send_codec.plfreq) : -1);
305 DCHECK(codec_owner_.Encoder());
306 }
307 send_codec_inst_.plfreq = send_codec.plfreq;
308 send_codec_inst_.pacsize = send_codec.pacsize;
309 send_codec_inst_.channels = send_codec.channels;
310 send_codec_inst_.pltype = send_codec.pltype;
311
312 // Check if a change in Rate is required.
313 if (send_codec.rate != send_codec_inst_.rate) {
314 codec_owner_.SpeechEncoder()->SetTargetBitrate(send_codec.rate);
315 send_codec_inst_.rate = send_codec.rate;
316 }
317
318 codec_fec_enabled_ = codec_fec_enabled_ &&
319 codec_owner_.SpeechEncoder()->SetFec(codec_fec_enabled_);
320
321 return 0;
Henrik Lundin046319e2015-03-30 17:00:44322}
323
Karl Wiberg48a57c62015-05-18 12:52:29324void CodecManager::RegisterEncoder(
325 AudioEncoderMutable* external_speech_encoder) {
326 // Make up a CodecInst.
327 send_codec_inst_.channels = external_speech_encoder->NumChannels();
328 send_codec_inst_.plfreq = external_speech_encoder->SampleRateHz();
Peter Kastinga0ad2482015-08-24 21:52:23329 send_codec_inst_.pacsize = rtc::CheckedDivExact(
330 static_cast<int>(external_speech_encoder->Max10MsFramesInAPacket() *
331 send_codec_inst_.plfreq),
332 100);
Karl Wiberg48a57c62015-05-18 12:52:29333 send_codec_inst_.pltype = -1; // Not valid.
334 send_codec_inst_.rate = -1; // Not valid.
335 static const char kName[] = "external";
336 memcpy(send_codec_inst_.plname, kName, sizeof(kName));
337
338 if (stereo_send_)
339 dtx_enabled_ = false;
340 codec_fec_enabled_ = codec_fec_enabled_ &&
341 codec_owner_.SpeechEncoder()->SetFec(codec_fec_enabled_);
342 int cng_pt = dtx_enabled_
343 ? CngPayloadType(external_speech_encoder->SampleRateHz())
344 : -1;
345 int red_pt = red_enabled_ ? RedPayloadType(send_codec_inst_.plfreq) : -1;
346 codec_owner_.SetEncoders(external_speech_encoder, cng_pt, vad_mode_, red_pt);
347}
348
349int CodecManager::GetCodecInst(CodecInst* current_codec) const {
Henrik Lundin046319e2015-03-30 17:00:44350 int dummy_id = 0;
351 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, dummy_id,
352 "SendCodec()");
353
Karl Wiberg6d216ed2015-05-07 13:49:23354 if (!codec_owner_.Encoder()) {
Henrik Lundin046319e2015-03-30 17:00:44355 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, dummy_id,
356 "SendCodec Failed, no codec is registered");
357 return -1;
358 }
Karl Wiberg6d216ed2015-05-07 13:49:23359 *current_codec = send_codec_inst_;
Henrik Lundin046319e2015-03-30 17:00:44360 return 0;
361}
362
Henrik Lundin046319e2015-03-30 17:00:44363bool CodecManager::SetCopyRed(bool enable) {
364 if (enable && codec_fec_enabled_) {
365 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
366 "Codec internal FEC and RED cannot be co-enabled.");
367 return false;
368 }
Karl Wiberg6d216ed2015-05-07 13:49:23369 if (enable && RedPayloadType(send_codec_inst_.plfreq) == -1) {
370 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
371 "Cannot enable RED at %i Hz.", send_codec_inst_.plfreq);
Henrik Lundin046319e2015-03-30 17:00:44372 return false;
373 }
Karl Wiberg6d216ed2015-05-07 13:49:23374 if (red_enabled_ != enable) {
375 red_enabled_ = enable;
Karl Wiberg48a57c62015-05-18 12:52:29376 if (codec_owner_.Encoder()) {
377 int cng_pt = dtx_enabled_ ? CngPayloadType(send_codec_inst_.plfreq) : -1;
378 int red_pt = red_enabled_ ? RedPayloadType(send_codec_inst_.plfreq) : -1;
379 codec_owner_.ChangeCngAndRed(cng_pt, vad_mode_, red_pt);
380 }
Karl Wiberg6d216ed2015-05-07 13:49:23381 }
Henrik Lundin046319e2015-03-30 17:00:44382 return true;
383}
384
Karl Wiberg6d216ed2015-05-07 13:49:23385int CodecManager::SetVAD(bool enable, ACMVADMode mode) {
Henrik Lundin046319e2015-03-30 17:00:44386 // Sanity check of the mode.
Karl Wiberg6d216ed2015-05-07 13:49:23387 DCHECK(mode == VADNormal || mode == VADLowBitrate || mode == VADAggr ||
388 mode == VADVeryAggr);
Henrik Lundin046319e2015-03-30 17:00:44389
390 // Check that the send codec is mono. We don't support VAD/DTX for stereo
391 // sending.
Karl Wiberg6d216ed2015-05-07 13:49:23392 if (enable && stereo_send_) {
Henrik Lundin046319e2015-03-30 17:00:44393 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
394 "VAD/DTX not supported for stereo sending");
395 dtx_enabled_ = false;
Henrik Lundin046319e2015-03-30 17:00:44396 return -1;
397 }
398
Henrik Lundin046319e2015-03-30 17:00:44399 // If a send codec is registered, set VAD/DTX for the codec.
Karl Wiberg6d216ed2015-05-07 13:49:23400 if (IsOpus(send_codec_inst_)) {
401 // VAD/DTX not supported.
Henrik Lundin046319e2015-03-30 17:00:44402 dtx_enabled_ = false;
Karl Wiberg6d216ed2015-05-07 13:49:23403 return 0;
404 }
405
406 if (dtx_enabled_ != enable || vad_mode_ != mode) {
407 dtx_enabled_ = enable;
408 vad_mode_ = mode;
Karl Wiberg48a57c62015-05-18 12:52:29409 if (codec_owner_.Encoder()) {
410 int cng_pt = dtx_enabled_ ? CngPayloadType(send_codec_inst_.plfreq) : -1;
411 int red_pt = red_enabled_ ? RedPayloadType(send_codec_inst_.plfreq) : -1;
412 codec_owner_.ChangeCngAndRed(cng_pt, vad_mode_, red_pt);
413 }
Henrik Lundin046319e2015-03-30 17:00:44414 }
415 return 0;
416}
417
418void CodecManager::VAD(bool* dtx_enabled,
419 bool* vad_enabled,
420 ACMVADMode* mode) const {
421 *dtx_enabled = dtx_enabled_;
Karl Wiberg6d216ed2015-05-07 13:49:23422 *vad_enabled = dtx_enabled_;
Henrik Lundin046319e2015-03-30 17:00:44423 *mode = vad_mode_;
424}
425
426int CodecManager::SetCodecFEC(bool enable_codec_fec) {
427 if (enable_codec_fec == true && red_enabled_ == true) {
428 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
429 "Codec internal FEC and RED cannot be co-enabled.");
430 return -1;
431 }
432
Karl Wiberg6d216ed2015-05-07 13:49:23433 CHECK(codec_owner_.SpeechEncoder());
434 codec_fec_enabled_ = codec_owner_.SpeechEncoder()->SetFec(enable_codec_fec) &&
435 enable_codec_fec;
436 return codec_fec_enabled_ == enable_codec_fec ? 0 : -1;
Henrik Lundin046319e2015-03-30 17:00:44437}
438
Karl Wiberg6d216ed2015-05-07 13:49:23439AudioDecoder* CodecManager::GetAudioDecoder(const CodecInst& codec) {
440 return IsIsac(codec) ? codec_owner_.GetIsacDecoder() : nullptr;
Henrik Lundin046319e2015-03-30 17:00:44441}
442
Karl Wiberg6d216ed2015-05-07 13:49:23443int CodecManager::CngPayloadType(int sample_rate_hz) const {
444 switch (sample_rate_hz) {
445 case 8000:
446 return cng_nb_pltype_;
447 case 16000:
448 return cng_wb_pltype_;
449 case 32000:
450 return cng_swb_pltype_;
451 case 48000:
452 return cng_fb_pltype_;
453 default:
454 FATAL() << sample_rate_hz << " Hz is not supported";
Henrik Lundindc044342015-04-13 07:31:16455 return -1;
456 }
Karl Wiberg6d216ed2015-05-07 13:49:23457}
458
459int CodecManager::RedPayloadType(int sample_rate_hz) const {
460 switch (sample_rate_hz) {
461 case 8000:
462 return red_nb_pltype_;
463 case 16000:
464 case 32000:
465 case 48000:
466 return -1;
467 default:
468 FATAL() << sample_rate_hz << " Hz is not supported";
469 return -1;
470 }
Henrik Lundin046319e2015-03-30 17:00:44471}
472
473} // namespace acm2
474} // namespace webrtc