• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2012 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/audio_coding_module_impl.h"
12 
13 #include <assert.h>
14 #include <stdlib.h>
15 #include <vector>
16 
17 #include "webrtc/base/checks.h"
18 #include "webrtc/engine_configurations.h"
19 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
20 #include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
21 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
22 #include "webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h"
23 #include "webrtc/modules/audio_coding/main/acm2/acm_resampler.h"
24 #include "webrtc/modules/audio_coding/main/acm2/call_statistics.h"
25 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
26 #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
27 #include "webrtc/system_wrappers/interface/trace.h"
28 #include "webrtc/typedefs.h"
29 
30 namespace webrtc {
31 
32 namespace acm2 {
33 
34 enum {
35   kACMToneEnd = 999
36 };
37 
38 // Maximum number of bytes in one packet (PCM16B, 20 ms packets, stereo).
39 enum {
40   kMaxPacketSize = 2560
41 };
42 
43 // Maximum number of payloads that can be packed in one RED packet. For
44 // regular RED, we only pack two payloads. In case of dual-streaming, in worst
45 // case we might pack 3 payloads in one RED packet.
46 enum {
47   kNumRedFragmentationVectors = 2,
48   kMaxNumFragmentationVectors = 3
49 };
50 
51 // If packet N is arrived all packets prior to N - |kNackThresholdPackets| which
52 // are not received are considered as lost, and appear in NACK list.
53 enum {
54   kNackThresholdPackets = 2
55 };
56 
57 namespace {
58 
59 // TODO(turajs): the same functionality is used in NetEq. If both classes
60 // need them, make it a static function in ACMCodecDB.
IsCodecRED(const CodecInst * codec)61 bool IsCodecRED(const CodecInst* codec) {
62   return (STR_CASE_CMP(codec->plname, "RED") == 0);
63 }
64 
IsCodecRED(int index)65 bool IsCodecRED(int index) {
66   return (IsCodecRED(&ACMCodecDB::database_[index]));
67 }
68 
IsCodecCN(const CodecInst * codec)69 bool IsCodecCN(const CodecInst* codec) {
70   return (STR_CASE_CMP(codec->plname, "CN") == 0);
71 }
72 
IsCodecCN(int index)73 bool IsCodecCN(int index) {
74   return (IsCodecCN(&ACMCodecDB::database_[index]));
75 }
76 
77 // Stereo-to-mono can be used as in-place.
DownMix(const AudioFrame & frame,int length_out_buff,int16_t * out_buff)78 int DownMix(const AudioFrame& frame, int length_out_buff, int16_t* out_buff) {
79   if (length_out_buff < frame.samples_per_channel_) {
80     return -1;
81   }
82   for (int n = 0; n < frame.samples_per_channel_; ++n)
83     out_buff[n] = (frame.data_[2 * n] + frame.data_[2 * n + 1]) >> 1;
84   return 0;
85 }
86 
87 // Mono-to-stereo can be used as in-place.
UpMix(const AudioFrame & frame,int length_out_buff,int16_t * out_buff)88 int UpMix(const AudioFrame& frame, int length_out_buff, int16_t* out_buff) {
89   if (length_out_buff < frame.samples_per_channel_) {
90     return -1;
91   }
92   for (int n = frame.samples_per_channel_ - 1; n >= 0; --n) {
93     out_buff[2 * n + 1] = frame.data_[n];
94     out_buff[2 * n] = frame.data_[n];
95   }
96   return 0;
97 }
98 
99 // Return 1 if timestamp t1 is less than timestamp t2, while compensating for
100 // wrap-around.
TimestampLessThan(uint32_t t1,uint32_t t2)101 static int TimestampLessThan(uint32_t t1, uint32_t t2) {
102   uint32_t kHalfFullRange = static_cast<uint32_t>(0xFFFFFFFF) / 2;
103   if (t1 == t2) {
104     return 0;
105   } else if (t1 < t2) {
106     if (t2 - t1 < kHalfFullRange)
107       return 1;
108     return 0;
109   } else {
110     if (t1 - t2 < kHalfFullRange)
111       return 0;
112     return 1;
113   }
114 }
115 
116 }  // namespace
117 
AudioCodingModuleImpl(const AudioCodingModule::Config & config)118 AudioCodingModuleImpl::AudioCodingModuleImpl(
119     const AudioCodingModule::Config& config)
120     : acm_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
121       id_(config.id),
122       expected_codec_ts_(0xD87F3F9F),
123       expected_in_ts_(0xD87F3F9F),
124       send_codec_inst_(),
125       cng_nb_pltype_(255),
126       cng_wb_pltype_(255),
127       cng_swb_pltype_(255),
128       cng_fb_pltype_(255),
129       red_pltype_(255),
130       vad_enabled_(false),
131       dtx_enabled_(false),
132       vad_mode_(VADNormal),
133       stereo_send_(false),
134       current_send_codec_idx_(-1),
135       send_codec_registered_(false),
136       receiver_(config),
137       is_first_red_(true),
138       red_enabled_(false),
139       last_red_timestamp_(0),
140       codec_fec_enabled_(false),
141       previous_pltype_(255),
142       aux_rtp_header_(NULL),
143       receiver_initialized_(false),
144       secondary_send_codec_inst_(),
145       codec_timestamp_(expected_codec_ts_),
146       first_10ms_data_(false),
147       callback_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
148       packetization_callback_(NULL),
149       vad_callback_(NULL) {
150 
151   // Nullify send codec memory, set payload type and set codec name to
152   // invalid values.
153   const char no_name[] = "noCodecRegistered";
154   strncpy(send_codec_inst_.plname, no_name, RTP_PAYLOAD_NAME_SIZE - 1);
155   send_codec_inst_.pltype = -1;
156 
157   strncpy(secondary_send_codec_inst_.plname, no_name,
158           RTP_PAYLOAD_NAME_SIZE - 1);
159   secondary_send_codec_inst_.pltype = -1;
160 
161   for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++) {
162     codecs_[i] = NULL;
163     mirror_codec_idx_[i] = -1;
164   }
165 
166   // Allocate memory for RED.
167   red_buffer_ = new uint8_t[MAX_PAYLOAD_SIZE_BYTE];
168 
169   // TODO(turajs): This might not be exactly how this class is supposed to work.
170   // The external usage might be that |fragmentationVectorSize| has to match
171   // the allocated space for the member-arrays, while here, we allocate
172   // according to the maximum number of fragmentations and change
173   // |fragmentationVectorSize| on-the-fly based on actual number of
174   // fragmentations. However, due to copying to local variable before calling
175   // SendData, the RTP module receives a "valid" fragmentation, where allocated
176   // space matches |fragmentationVectorSize|, therefore, this should not cause
177   // any problem. A better approach is not using RTPFragmentationHeader as
178   // member variable, instead, use an ACM-specific structure to hold RED-related
179   // data. See module_common_type.h for the definition of
180   // RTPFragmentationHeader.
181   fragmentation_.VerifyAndAllocateFragmentationHeader(
182       kMaxNumFragmentationVectors);
183 
184   // Register the default payload type for RED and for CNG at sampling rates of
185   // 8, 16, 32 and 48 kHz.
186   for (int i = (ACMCodecDB::kNumCodecs - 1); i >= 0; i--) {
187     if (IsCodecRED(i)) {
188       red_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
189     } else if (IsCodecCN(i)) {
190       if (ACMCodecDB::database_[i].plfreq == 8000) {
191         cng_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
192       } else if (ACMCodecDB::database_[i].plfreq == 16000) {
193         cng_wb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
194       } else if (ACMCodecDB::database_[i].plfreq == 32000) {
195         cng_swb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
196       } else if (ACMCodecDB::database_[i].plfreq == 48000) {
197         cng_fb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
198       }
199     }
200   }
201 
202   if (InitializeReceiverSafe() < 0) {
203     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
204                  "Cannot initialize receiver");
205   }
206   WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceAudioCoding, id_, "Created");
207 }
208 
~AudioCodingModuleImpl()209 AudioCodingModuleImpl::~AudioCodingModuleImpl() {
210   {
211     CriticalSectionScoped lock(acm_crit_sect_);
212     current_send_codec_idx_ = -1;
213 
214     for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++) {
215       if (codecs_[i] != NULL) {
216         // Mirror index holds the address of the codec memory.
217         assert(mirror_codec_idx_[i] > -1);
218         if (codecs_[mirror_codec_idx_[i]] != NULL) {
219           delete codecs_[mirror_codec_idx_[i]];
220           codecs_[mirror_codec_idx_[i]] = NULL;
221         }
222 
223         codecs_[i] = NULL;
224       }
225     }
226 
227     if (red_buffer_ != NULL) {
228       delete[] red_buffer_;
229       red_buffer_ = NULL;
230     }
231   }
232 
233   if (aux_rtp_header_ != NULL) {
234     delete aux_rtp_header_;
235     aux_rtp_header_ = NULL;
236   }
237 
238   delete callback_crit_sect_;
239   callback_crit_sect_ = NULL;
240 
241   delete acm_crit_sect_;
242   acm_crit_sect_ = NULL;
243   WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceAudioCoding, id_,
244                "Destroyed");
245 }
246 
ChangeUniqueId(const int32_t id)247 int32_t AudioCodingModuleImpl::ChangeUniqueId(const int32_t id) {
248   {
249     CriticalSectionScoped lock(acm_crit_sect_);
250     id_ = id;
251 
252     for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++) {
253       if (codecs_[i] != NULL) {
254         codecs_[i]->SetUniqueID(id);
255       }
256     }
257   }
258 
259   receiver_.set_id(id_);
260   return 0;
261 }
262 
263 // Returns the number of milliseconds until the module want a
264 // worker thread to call Process.
TimeUntilNextProcess()265 int32_t AudioCodingModuleImpl::TimeUntilNextProcess() {
266   CriticalSectionScoped lock(acm_crit_sect_);
267 
268   if (!HaveValidEncoder("TimeUntilNextProcess")) {
269     return -1;
270   }
271   return codecs_[current_send_codec_idx_]->SamplesLeftToEncode() /
272       (send_codec_inst_.plfreq / 1000);
273 }
274 
Process()275 int32_t AudioCodingModuleImpl::Process() {
276   bool dual_stream;
277   {
278     CriticalSectionScoped lock(acm_crit_sect_);
279     dual_stream = (secondary_encoder_.get() != NULL);
280   }
281   if (dual_stream) {
282     return ProcessDualStream();
283   }
284   return ProcessSingleStream();
285 }
286 
EncodeFragmentation(int fragmentation_index,int payload_type,uint32_t current_timestamp,ACMGenericCodec * encoder,uint8_t * stream)287 int AudioCodingModuleImpl::EncodeFragmentation(int fragmentation_index,
288                                                int payload_type,
289                                                uint32_t current_timestamp,
290                                                ACMGenericCodec* encoder,
291                                                uint8_t* stream) {
292   int16_t len_bytes = MAX_PAYLOAD_SIZE_BYTE;
293   uint32_t rtp_timestamp;
294   WebRtcACMEncodingType encoding_type;
295   if (encoder->Encode(stream, &len_bytes, &rtp_timestamp, &encoding_type) < 0) {
296     return -1;
297   }
298   assert(encoding_type == kActiveNormalEncoded);
299   assert(len_bytes > 0);
300 
301   fragmentation_.fragmentationLength[fragmentation_index] = len_bytes;
302   fragmentation_.fragmentationPlType[fragmentation_index] = payload_type;
303   fragmentation_.fragmentationTimeDiff[fragmentation_index] =
304       static_cast<uint16_t>(current_timestamp - rtp_timestamp);
305   fragmentation_.fragmentationVectorSize++;
306   return len_bytes;
307 }
308 
309 // Primary payloads are sent immediately, whereas a single secondary payload is
310 // buffered to be combined with "the next payload."
311 // Normally "the next payload" would be a primary payload. In case two
312 // consecutive secondary payloads are generated with no primary payload in
313 // between, then two secondary payloads are packed in one RED.
ProcessDualStream()314 int AudioCodingModuleImpl::ProcessDualStream() {
315   uint8_t stream[kMaxNumFragmentationVectors * MAX_PAYLOAD_SIZE_BYTE];
316   uint32_t current_timestamp;
317   int16_t length_bytes = 0;
318   RTPFragmentationHeader my_fragmentation;
319 
320   uint8_t my_red_payload_type;
321 
322   {
323     CriticalSectionScoped lock(acm_crit_sect_);
324     // Check if there is an encoder before.
325     if (!HaveValidEncoder("ProcessDualStream") ||
326         secondary_encoder_.get() == NULL) {
327       return -1;
328     }
329     ACMGenericCodec* primary_encoder = codecs_[current_send_codec_idx_];
330     // If primary encoder has a full frame of audio to generate payload.
331     bool primary_ready_to_encode = primary_encoder->HasFrameToEncode();
332     // If the secondary encoder has a frame of audio to generate a payload.
333     bool secondary_ready_to_encode = secondary_encoder_->HasFrameToEncode();
334 
335     if (!primary_ready_to_encode && !secondary_ready_to_encode) {
336       // Nothing to send.
337       return 0;
338     }
339     int len_bytes_previous_secondary = static_cast<int>(
340         fragmentation_.fragmentationLength[2]);
341     assert(len_bytes_previous_secondary <= MAX_PAYLOAD_SIZE_BYTE);
342     bool has_previous_payload = len_bytes_previous_secondary > 0;
343 
344     uint32_t primary_timestamp = primary_encoder->EarliestTimestamp();
345     uint32_t secondary_timestamp = secondary_encoder_->EarliestTimestamp();
346 
347     if (!has_previous_payload && !primary_ready_to_encode &&
348         secondary_ready_to_encode) {
349       // Secondary payload will be the ONLY bit-stream. Encode by secondary
350       // encoder, store the payload, and return. No packet is sent.
351       int16_t len_bytes = MAX_PAYLOAD_SIZE_BYTE;
352       WebRtcACMEncodingType encoding_type;
353       if (secondary_encoder_->Encode(red_buffer_, &len_bytes,
354                                      &last_red_timestamp_,
355                                      &encoding_type) < 0) {
356         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
357                      "ProcessDual(): Encoding of secondary encoder Failed");
358         return -1;
359       }
360       assert(len_bytes > 0);
361       assert(encoding_type == kActiveNormalEncoded);
362       assert(len_bytes <= MAX_PAYLOAD_SIZE_BYTE);
363       fragmentation_.fragmentationLength[2] = len_bytes;
364       return 0;
365     }
366 
367     // Initialize with invalid but different values, so later can have sanity
368     // check if they are different.
369     int index_primary = -1;
370     int index_secondary = -2;
371     int index_previous_secondary = -3;
372 
373     if (primary_ready_to_encode) {
374       index_primary = secondary_ready_to_encode ?
375           TimestampLessThan(primary_timestamp, secondary_timestamp) : 0;
376       index_primary += has_previous_payload ?
377           TimestampLessThan(primary_timestamp, last_red_timestamp_) : 0;
378     }
379 
380     if (secondary_ready_to_encode) {
381       // Timestamp of secondary payload can only be less than primary payload,
382       // but is always larger than the timestamp of previous secondary payload.
383       index_secondary = primary_ready_to_encode ?
384           (1 - TimestampLessThan(primary_timestamp, secondary_timestamp)) : 0;
385     }
386 
387     if (has_previous_payload) {
388       index_previous_secondary = primary_ready_to_encode ?
389           (1 - TimestampLessThan(primary_timestamp, last_red_timestamp_)) : 0;
390       // If secondary is ready it always have a timestamp larger than previous
391       // secondary. So the index is either 0 or 1.
392       index_previous_secondary += secondary_ready_to_encode ? 1 : 0;
393     }
394 
395     // Indices must not be equal.
396     assert(index_primary != index_secondary);
397     assert(index_primary != index_previous_secondary);
398     assert(index_secondary != index_previous_secondary);
399 
400     // One of the payloads has to be at position zero.
401     assert(index_primary == 0 || index_secondary == 0 ||
402            index_previous_secondary == 0);
403 
404     // Timestamp of the RED payload.
405     if (index_primary == 0) {
406       current_timestamp = primary_timestamp;
407     } else if (index_secondary == 0) {
408       current_timestamp = secondary_timestamp;
409     } else {
410       current_timestamp = last_red_timestamp_;
411     }
412 
413     fragmentation_.fragmentationVectorSize = 0;
414     if (has_previous_payload) {
415       assert(index_previous_secondary >= 0 &&
416              index_previous_secondary < kMaxNumFragmentationVectors);
417       assert(len_bytes_previous_secondary <= MAX_PAYLOAD_SIZE_BYTE);
418       memcpy(&stream[index_previous_secondary * MAX_PAYLOAD_SIZE_BYTE],
419              red_buffer_, sizeof(stream[0]) * len_bytes_previous_secondary);
420       fragmentation_.fragmentationLength[index_previous_secondary] =
421           len_bytes_previous_secondary;
422       fragmentation_.fragmentationPlType[index_previous_secondary] =
423           secondary_send_codec_inst_.pltype;
424       fragmentation_.fragmentationTimeDiff[index_previous_secondary] =
425           static_cast<uint16_t>(current_timestamp - last_red_timestamp_);
426       fragmentation_.fragmentationVectorSize++;
427     }
428 
429     if (primary_ready_to_encode) {
430       assert(index_primary >= 0 && index_primary < kMaxNumFragmentationVectors);
431       int i = index_primary * MAX_PAYLOAD_SIZE_BYTE;
432       if (EncodeFragmentation(index_primary, send_codec_inst_.pltype,
433                               current_timestamp, primary_encoder,
434                               &stream[i]) < 0) {
435         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
436                      "ProcessDualStream(): Encoding of primary encoder Failed");
437         return -1;
438       }
439     }
440 
441     if (secondary_ready_to_encode) {
442       assert(index_secondary >= 0 &&
443              index_secondary < kMaxNumFragmentationVectors - 1);
444       int i = index_secondary * MAX_PAYLOAD_SIZE_BYTE;
445       if (EncodeFragmentation(index_secondary,
446                               secondary_send_codec_inst_.pltype,
447                               current_timestamp, secondary_encoder_.get(),
448                               &stream[i]) < 0) {
449         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
450                      "ProcessDualStream(): Encoding of secondary encoder "
451                      "Failed");
452         return -1;
453       }
454     }
455     // Copy to local variable, as it will be used outside the ACM lock.
456     my_fragmentation.CopyFrom(fragmentation_);
457     my_red_payload_type = red_pltype_;
458     length_bytes = 0;
459     for (int n = 0; n < fragmentation_.fragmentationVectorSize; n++) {
460       length_bytes += fragmentation_.fragmentationLength[n];
461     }
462   }
463 
464   {
465     CriticalSectionScoped lock(callback_crit_sect_);
466     if (packetization_callback_ != NULL) {
467       // Callback with payload data, including redundant data (RED).
468       if (packetization_callback_->SendData(kAudioFrameSpeech,
469                                             my_red_payload_type,
470                                             current_timestamp, stream,
471                                             length_bytes,
472                                             &my_fragmentation) < 0) {
473         return -1;
474       }
475     }
476   }
477 
478   {
479     CriticalSectionScoped lock(acm_crit_sect_);
480     // Now that data is sent, clean up fragmentation.
481     ResetFragmentation(0);
482   }
483   return 0;
484 }
485 
486 // Process any pending tasks such as timeouts.
ProcessSingleStream()487 int AudioCodingModuleImpl::ProcessSingleStream() {
488   // Make room for 1 RED payload.
489   uint8_t stream[2 * MAX_PAYLOAD_SIZE_BYTE];
490   // TODO(turajs): |length_bytes| & |red_length_bytes| can be of type int if
491   // ACMGenericCodec::Encode() & ACMGenericCodec::GetRedPayload() allows.
492   int16_t length_bytes = 2 * MAX_PAYLOAD_SIZE_BYTE;
493   int16_t red_length_bytes = length_bytes;
494   uint32_t rtp_timestamp;
495   int status;
496   WebRtcACMEncodingType encoding_type;
497   FrameType frame_type = kAudioFrameSpeech;
498   uint8_t current_payload_type = 0;
499   bool has_data_to_send = false;
500   bool red_active = false;
501   RTPFragmentationHeader my_fragmentation;
502 
503   // Keep the scope of the ACM critical section limited.
504   {
505     CriticalSectionScoped lock(acm_crit_sect_);
506     // Check if there is an encoder before.
507     if (!HaveValidEncoder("ProcessSingleStream")) {
508       return -1;
509     }
510     status = codecs_[current_send_codec_idx_]->Encode(stream, &length_bytes,
511                                                       &rtp_timestamp,
512                                                       &encoding_type);
513     if (status < 0) {
514       // Encode failed.
515       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
516                    "ProcessSingleStream(): Encoding Failed");
517       length_bytes = 0;
518       return -1;
519     } else if (status == 0) {
520       // Not enough data.
521       return 0;
522     } else {
523       switch (encoding_type) {
524         case kNoEncoding: {
525           current_payload_type = previous_pltype_;
526           frame_type = kFrameEmpty;
527           length_bytes = 0;
528           break;
529         }
530         case kActiveNormalEncoded:
531         case kPassiveNormalEncoded: {
532           current_payload_type = static_cast<uint8_t>(send_codec_inst_.pltype);
533           frame_type = kAudioFrameSpeech;
534           break;
535         }
536         case kPassiveDTXNB: {
537           current_payload_type = cng_nb_pltype_;
538           frame_type = kAudioFrameCN;
539           is_first_red_ = true;
540           break;
541         }
542         case kPassiveDTXWB: {
543           current_payload_type = cng_wb_pltype_;
544           frame_type = kAudioFrameCN;
545           is_first_red_ = true;
546           break;
547         }
548         case kPassiveDTXSWB: {
549           current_payload_type = cng_swb_pltype_;
550           frame_type = kAudioFrameCN;
551           is_first_red_ = true;
552           break;
553         }
554         case kPassiveDTXFB: {
555           current_payload_type = cng_fb_pltype_;
556           frame_type = kAudioFrameCN;
557           is_first_red_ = true;
558           break;
559         }
560       }
561       has_data_to_send = true;
562       previous_pltype_ = current_payload_type;
563 
564       // Redundancy encode is done here. The two bitstreams packetized into
565       // one RTP packet and the fragmentation points are set.
566       // Only apply RED on speech data.
567       if ((red_enabled_) &&
568           ((encoding_type == kActiveNormalEncoded) ||
569               (encoding_type == kPassiveNormalEncoded))) {
570         // RED is enabled within this scope.
571         //
572         // Note that, a special solution exists for iSAC since it is the only
573         // codec for which GetRedPayload has a non-empty implementation.
574         //
575         // Summary of the RED scheme below (use iSAC as example):
576         //
577         //  1st (is_first_red_ is true) encoded iSAC frame (primary #1) =>
578         //      - call GetRedPayload() and store redundancy for packet #1 in
579         //        second fragment of RED buffer (old data)
580         //      - drop the primary iSAC frame
581         //      - don't call SendData
582         //  2nd (is_first_red_ is false) encoded iSAC frame (primary #2) =>
583         //      - store primary #2 in 1st fragment of RED buffer and send the
584         //        combined packet
585         //      - the transmitted packet contains primary #2 (new) and
586         //        redundancy for packet #1 (old)
587         //      - call GetRed_Payload() and store redundancy for packet #2 in
588         //        second fragment of RED buffer
589         //
590         //  ...
591         //
592         //  Nth encoded iSAC frame (primary #N) =>
593         //      - store primary #N in 1st fragment of RED buffer and send the
594         //        combined packet
595         //      - the transmitted packet contains primary #N (new) and
596         //        reduncancy for packet #(N-1) (old)
597         //      - call GetRedPayload() and store redundancy for packet #N in
598         //        second fragment of RED buffer
599         //
600         //  For all other codecs, GetRedPayload does nothing and returns -1 =>
601         //  redundant data is only a copy.
602         //
603         //  First combined packet contains : #2 (new) and #1 (old)
604         //  Second combined packet contains: #3 (new) and #2 (old)
605         //  Third combined packet contains : #4 (new) and #3 (old)
606         //
607         //  Hence, even if every second packet is dropped, perfect
608         //  reconstruction is possible.
609         red_active = true;
610 
611         has_data_to_send = false;
612         // Skip the following part for the first packet in a RED session.
613         if (!is_first_red_) {
614           // Rearrange stream such that RED packets are included.
615           // Replace stream now that we have stored current stream.
616           memcpy(stream + fragmentation_.fragmentationOffset[1], red_buffer_,
617                  fragmentation_.fragmentationLength[1]);
618           // Update the fragmentation time difference vector, in number of
619           // timestamps.
620           uint16_t time_since_last = static_cast<uint16_t>(
621               rtp_timestamp - last_red_timestamp_);
622 
623           // Update fragmentation vectors.
624           fragmentation_.fragmentationPlType[1] =
625               fragmentation_.fragmentationPlType[0];
626           fragmentation_.fragmentationTimeDiff[1] = time_since_last;
627           has_data_to_send = true;
628         }
629 
630         // Insert new packet length.
631         fragmentation_.fragmentationLength[0] = length_bytes;
632 
633         // Insert new packet payload type.
634         fragmentation_.fragmentationPlType[0] = current_payload_type;
635         last_red_timestamp_ = rtp_timestamp;
636 
637         // Can be modified by the GetRedPayload() call if iSAC is utilized.
638         red_length_bytes = length_bytes;
639 
640         // A fragmentation header is provided => packetization according to
641         // RFC 2198 (RTP Payload for Redundant Audio Data) will be used.
642         // First fragment is the current data (new).
643         // Second fragment is the previous data (old).
644         length_bytes = static_cast<int16_t>(
645             fragmentation_.fragmentationLength[0] +
646             fragmentation_.fragmentationLength[1]);
647 
648         // Get, and store, redundant data from the encoder based on the recently
649         // encoded frame.
650         // NOTE - only iSAC contains an implementation; all other codecs does
651         // nothing and returns -1.
652         if (codecs_[current_send_codec_idx_]->GetRedPayload(
653             red_buffer_, &red_length_bytes) == -1) {
654           // The codec was not iSAC => use current encoder output as redundant
655           // data instead (trivial RED scheme).
656           memcpy(red_buffer_, stream, red_length_bytes);
657         }
658 
659         is_first_red_ = false;
660         // Update payload type with RED payload type.
661         current_payload_type = red_pltype_;
662         // We have packed 2 payloads.
663         fragmentation_.fragmentationVectorSize = kNumRedFragmentationVectors;
664 
665         // Copy to local variable, as it will be used outside ACM lock.
666         my_fragmentation.CopyFrom(fragmentation_);
667         // Store RED length.
668         fragmentation_.fragmentationLength[1] = red_length_bytes;
669       }
670     }
671   }
672 
673   if (has_data_to_send) {
674     CriticalSectionScoped lock(callback_crit_sect_);
675 
676     if (packetization_callback_ != NULL) {
677       if (red_active) {
678         // Callback with payload data, including redundant data (RED).
679         packetization_callback_->SendData(frame_type, current_payload_type,
680                                           rtp_timestamp, stream, length_bytes,
681                                           &my_fragmentation);
682       } else {
683         // Callback with payload data.
684         packetization_callback_->SendData(frame_type, current_payload_type,
685                                           rtp_timestamp, stream, length_bytes,
686                                           NULL);
687       }
688     }
689 
690     if (vad_callback_ != NULL) {
691       // Callback with VAD decision.
692       vad_callback_->InFrameType(static_cast<int16_t>(encoding_type));
693     }
694   }
695   return length_bytes;
696 }
697 
698 /////////////////////////////////////////
699 //   Sender
700 //
701 
702 // Initialize send codec.
InitializeSender()703 int AudioCodingModuleImpl::InitializeSender() {
704   CriticalSectionScoped lock(acm_crit_sect_);
705 
706   // Start with invalid values.
707   send_codec_registered_ = false;
708   current_send_codec_idx_ = -1;
709   send_codec_inst_.plname[0] = '\0';
710 
711   // Delete all encoders to start fresh.
712   for (int id = 0; id < ACMCodecDB::kMaxNumCodecs; id++) {
713     if (codecs_[id] != NULL) {
714       codecs_[id]->DestructEncoder();
715     }
716   }
717 
718   // Initialize RED.
719   is_first_red_ = true;
720   if (red_enabled_ || secondary_encoder_.get() != NULL) {
721     if (red_buffer_ != NULL) {
722       memset(red_buffer_, 0, MAX_PAYLOAD_SIZE_BYTE);
723     }
724     if (red_enabled_) {
725       ResetFragmentation(kNumRedFragmentationVectors);
726     } else {
727       ResetFragmentation(0);
728     }
729   }
730 
731   return 0;
732 }
733 
ResetEncoder()734 int AudioCodingModuleImpl::ResetEncoder() {
735   CriticalSectionScoped lock(acm_crit_sect_);
736   if (!HaveValidEncoder("ResetEncoder")) {
737     return -1;
738   }
739   return codecs_[current_send_codec_idx_]->ResetEncoder();
740 }
741 
CreateCodec(const CodecInst & codec)742 ACMGenericCodec* AudioCodingModuleImpl::CreateCodec(const CodecInst& codec) {
743   ACMGenericCodec* my_codec = NULL;
744 
745   my_codec = ACMCodecDB::CreateCodecInstance(codec);
746   if (my_codec == NULL) {
747     // Error, could not create the codec.
748     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
749                  "ACMCodecDB::CreateCodecInstance() failed in CreateCodec()");
750     return my_codec;
751   }
752   my_codec->SetUniqueID(id_);
753 
754   return my_codec;
755 }
756 
757 // Check if the given codec is a valid to be registered as send codec.
IsValidSendCodec(const CodecInst & send_codec,bool is_primary_encoder,int acm_id,int * mirror_id)758 static int IsValidSendCodec(const CodecInst& send_codec,
759                             bool is_primary_encoder,
760                             int acm_id,
761                             int* mirror_id) {
762   if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
763     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
764                  "Wrong number of channels (%d, only mono and stereo are "
765                  "supported) for %s encoder", send_codec.channels,
766                  is_primary_encoder ? "primary" : "secondary");
767     return -1;
768   }
769 
770   int codec_id = ACMCodecDB::CodecNumber(send_codec, mirror_id);
771   if (codec_id < 0) {
772     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
773                  "Invalid codec setting for the send codec.");
774     return -1;
775   }
776 
777   // TODO(tlegrand): Remove this check. Already taken care of in
778   // ACMCodecDB::CodecNumber().
779   // Check if the payload-type is valid
780   if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
781     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
782                  "Invalid payload-type %d for %s.", send_codec.pltype,
783                  send_codec.plname);
784     return -1;
785   }
786 
787   // Telephone-event cannot be a send codec.
788   if (!STR_CASE_CMP(send_codec.plname, "telephone-event")) {
789     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
790                  "telephone-event cannot be a send codec");
791     *mirror_id = -1;
792     return -1;
793   }
794 
795   if (ACMCodecDB::codec_settings_[codec_id].channel_support
796       < send_codec.channels) {
797     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
798                  "%d number of channels not supportedn for %s.",
799                  send_codec.channels, send_codec.plname);
800     *mirror_id = -1;
801     return -1;
802   }
803 
804   if (!is_primary_encoder) {
805     // If registering the secondary encoder, then RED and CN are not valid
806     // choices as encoder.
807     if (IsCodecRED(&send_codec)) {
808       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
809                    "RED cannot be secondary codec");
810       *mirror_id = -1;
811       return -1;
812     }
813 
814     if (IsCodecCN(&send_codec)) {
815       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
816                    "DTX cannot be secondary codec");
817       *mirror_id = -1;
818       return -1;
819     }
820   }
821   return codec_id;
822 }
823 
RegisterSecondarySendCodec(const CodecInst & send_codec)824 int AudioCodingModuleImpl::RegisterSecondarySendCodec(
825     const CodecInst& send_codec) {
826   CriticalSectionScoped lock(acm_crit_sect_);
827   if (!send_codec_registered_) {
828     return -1;
829   }
830   // Primary and Secondary codecs should have the same sampling rates.
831   if (send_codec.plfreq != send_codec_inst_.plfreq) {
832     return -1;
833   }
834   int mirror_id;
835   int codec_id = IsValidSendCodec(send_codec, false, id_, &mirror_id);
836   if (codec_id < 0) {
837     return -1;
838   }
839   ACMGenericCodec* encoder = CreateCodec(send_codec);
840   WebRtcACMCodecParams codec_params;
841   // Initialize the codec before registering. For secondary codec VAD & DTX are
842   // disabled.
843   memcpy(&(codec_params.codec_inst), &send_codec, sizeof(CodecInst));
844   codec_params.enable_vad = false;
845   codec_params.enable_dtx = false;
846   codec_params.vad_mode = VADNormal;
847   // Force initialization.
848   if (encoder->InitEncoder(&codec_params, true) < 0) {
849     // Could not initialize, therefore cannot be registered.
850     delete encoder;
851     return -1;
852   }
853   secondary_encoder_.reset(encoder);
854   memcpy(&secondary_send_codec_inst_, &send_codec, sizeof(send_codec));
855 
856   // Disable VAD & DTX.
857   SetVADSafe(false, false, VADNormal);
858 
859   // Cleaning.
860   if (red_buffer_) {
861     memset(red_buffer_, 0, MAX_PAYLOAD_SIZE_BYTE);
862   }
863   ResetFragmentation(0);
864   return 0;
865 }
866 
UnregisterSecondarySendCodec()867 void AudioCodingModuleImpl::UnregisterSecondarySendCodec() {
868   CriticalSectionScoped lock(acm_crit_sect_);
869   if (secondary_encoder_.get() == NULL) {
870     return;
871   }
872   secondary_encoder_.reset();
873   ResetFragmentation(0);
874 }
875 
SecondarySendCodec(CodecInst * secondary_codec) const876 int AudioCodingModuleImpl::SecondarySendCodec(
877     CodecInst* secondary_codec) const {
878   CriticalSectionScoped lock(acm_crit_sect_);
879   if (secondary_encoder_.get() == NULL) {
880     return -1;
881   }
882   memcpy(secondary_codec, &secondary_send_codec_inst_,
883          sizeof(secondary_send_codec_inst_));
884   return 0;
885 }
886 
887 // Can be called multiple times for Codec, CNG, RED.
RegisterSendCodec(const CodecInst & send_codec)888 int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) {
889   int mirror_id;
890   int codec_id = IsValidSendCodec(send_codec, true, id_, &mirror_id);
891 
892   CriticalSectionScoped lock(acm_crit_sect_);
893 
894   // Check for reported errors from function IsValidSendCodec().
895   if (codec_id < 0) {
896     if (!send_codec_registered_) {
897       // This values has to be NULL if there is no codec registered.
898       current_send_codec_idx_ = -1;
899     }
900     return -1;
901   }
902 
903   // RED can be registered with other payload type. If not registered a default
904   // payload type is used.
905   if (IsCodecRED(&send_codec)) {
906     // TODO(tlegrand): Remove this check. Already taken care of in
907     // ACMCodecDB::CodecNumber().
908     // Check if the payload-type is valid
909     if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
910       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
911                    "Invalid payload-type %d for %s.", send_codec.pltype,
912                    send_codec.plname);
913       return -1;
914     }
915     // Set RED payload type.
916     red_pltype_ = static_cast<uint8_t>(send_codec.pltype);
917     return 0;
918   }
919 
920   // CNG can be registered with other payload type. If not registered the
921   // default payload types from codec database will be used.
922   if (IsCodecCN(&send_codec)) {
923     // CNG is registered.
924     switch (send_codec.plfreq) {
925       case 8000: {
926         cng_nb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
927         break;
928       }
929       case 16000: {
930         cng_wb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
931         break;
932       }
933       case 32000: {
934         cng_swb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
935         break;
936       }
937       case 48000: {
938         cng_fb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
939         break;
940       }
941       default: {
942         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
943                      "RegisterSendCodec() failed, invalid frequency for CNG "
944                      "registration");
945         return -1;
946       }
947     }
948     return 0;
949   }
950 
951   // Set Stereo, and make sure VAD and DTX is turned off.
952   if (send_codec.channels == 2) {
953     stereo_send_ = true;
954     if (vad_enabled_ || dtx_enabled_) {
955       WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
956                    "VAD/DTX is turned off, not supported when sending stereo.");
957     }
958     vad_enabled_ = false;
959     dtx_enabled_ = false;
960   } else {
961     stereo_send_ = false;
962   }
963 
964   // Check if the codec is already registered as send codec.
965   bool is_send_codec;
966   if (send_codec_registered_) {
967     int send_codec_mirror_id;
968     int send_codec_id = ACMCodecDB::CodecNumber(send_codec_inst_,
969                                                 &send_codec_mirror_id);
970     assert(send_codec_id >= 0);
971     is_send_codec = (send_codec_id == codec_id) ||
972         (mirror_id == send_codec_mirror_id);
973   } else {
974     is_send_codec = false;
975   }
976 
977   // If there is secondary codec registered and the new send codec has a
978   // sampling rate different than that of secondary codec, then unregister the
979   // secondary codec.
980   if (secondary_encoder_.get() != NULL &&
981       secondary_send_codec_inst_.plfreq != send_codec.plfreq) {
982     secondary_encoder_.reset();
983     ResetFragmentation(0);
984   }
985 
986   // If new codec, or new settings, register.
987   if (!is_send_codec) {
988     if (codecs_[mirror_id] == NULL) {
989       codecs_[mirror_id] = CreateCodec(send_codec);
990       if (codecs_[mirror_id] == NULL) {
991         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
992                      "Cannot Create the codec");
993         return -1;
994       }
995       mirror_codec_idx_[mirror_id] = mirror_id;
996     }
997 
998     if (mirror_id != codec_id) {
999       codecs_[codec_id] = codecs_[mirror_id];
1000       mirror_codec_idx_[codec_id] = mirror_id;
1001     }
1002 
1003     ACMGenericCodec* codec_ptr = codecs_[codec_id];
1004     WebRtcACMCodecParams codec_params;
1005 
1006     memcpy(&(codec_params.codec_inst), &send_codec, sizeof(CodecInst));
1007     codec_params.enable_vad = vad_enabled_;
1008     codec_params.enable_dtx = dtx_enabled_;
1009     codec_params.vad_mode = vad_mode_;
1010     // Force initialization.
1011     if (codec_ptr->InitEncoder(&codec_params, true) < 0) {
1012       // Could not initialize the encoder.
1013 
1014       // Check if already have a registered codec.
1015       // Depending on that different messages are logged.
1016       if (!send_codec_registered_) {
1017         current_send_codec_idx_ = -1;
1018         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1019                      "Cannot Initialize the encoder No Encoder is registered");
1020       } else {
1021         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1022                      "Cannot Initialize the encoder, continue encoding with "
1023                      "the previously registered codec");
1024       }
1025       return -1;
1026     }
1027 
1028     // Update states.
1029     dtx_enabled_ = codec_params.enable_dtx;
1030     vad_enabled_ = codec_params.enable_vad;
1031     vad_mode_ = codec_params.vad_mode;
1032 
1033     // Everything is fine so we can replace the previous codec with this one.
1034     if (send_codec_registered_) {
1035       // If we change codec we start fresh with RED.
1036       // This is not strictly required by the standard.
1037       is_first_red_ = true;
1038       codec_ptr->SetVAD(&dtx_enabled_, &vad_enabled_, &vad_mode_);
1039 
1040       if (!codec_ptr->HasInternalFEC()) {
1041         codec_fec_enabled_ = false;
1042       } else {
1043         if (codec_ptr->SetFEC(codec_fec_enabled_) < 0) {
1044           WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1045                        "Cannot set codec FEC");
1046           return -1;
1047         }
1048       }
1049     }
1050 
1051     current_send_codec_idx_ = codec_id;
1052     send_codec_registered_ = true;
1053     memcpy(&send_codec_inst_, &send_codec, sizeof(CodecInst));
1054     previous_pltype_ = send_codec_inst_.pltype;
1055     return 0;
1056   } else {
1057     // If codec is the same as already registered check if any parameters
1058     // has changed compared to the current values.
1059     // If any parameter is valid then apply it and record.
1060     bool force_init = false;
1061 
1062     if (mirror_id != codec_id) {
1063       codecs_[codec_id] = codecs_[mirror_id];
1064       mirror_codec_idx_[codec_id] = mirror_id;
1065     }
1066 
1067     // Check the payload type.
1068     if (send_codec.pltype != send_codec_inst_.pltype) {
1069       // At this point check if the given payload type is valid.
1070       // Record it later when the sampling frequency is changed
1071       // successfully.
1072       if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
1073         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1074                      "Out of range payload type");
1075         return -1;
1076       }
1077     }
1078 
1079     // If there is a codec that ONE instance of codec supports multiple
1080     // sampling frequencies, then we need to take care of it here.
1081     // one such a codec is iSAC. Both WB and SWB are encoded and decoded
1082     // with one iSAC instance. Therefore, we need to update the encoder
1083     // frequency if required.
1084     if (send_codec_inst_.plfreq != send_codec.plfreq) {
1085       force_init = true;
1086 
1087       // If sampling frequency is changed we have to start fresh with RED.
1088       is_first_red_ = true;
1089     }
1090 
1091     // If packet size or number of channels has changed, we need to
1092     // re-initialize the encoder.
1093     if (send_codec_inst_.pacsize != send_codec.pacsize) {
1094       force_init = true;
1095     }
1096     if (send_codec_inst_.channels != send_codec.channels) {
1097       force_init = true;
1098     }
1099 
1100     if (force_init) {
1101       WebRtcACMCodecParams codec_params;
1102 
1103       memcpy(&(codec_params.codec_inst), &send_codec, sizeof(CodecInst));
1104       codec_params.enable_vad = vad_enabled_;
1105       codec_params.enable_dtx = dtx_enabled_;
1106       codec_params.vad_mode = vad_mode_;
1107 
1108       // Force initialization.
1109       if (codecs_[current_send_codec_idx_]->InitEncoder(&codec_params,
1110                                                         true) < 0) {
1111         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1112                      "Could not change the codec packet-size.");
1113         return -1;
1114       }
1115 
1116       send_codec_inst_.plfreq = send_codec.plfreq;
1117       send_codec_inst_.pacsize = send_codec.pacsize;
1118       send_codec_inst_.channels = send_codec.channels;
1119     }
1120 
1121     // If the change of sampling frequency has been successful then
1122     // we store the payload-type.
1123     send_codec_inst_.pltype = send_codec.pltype;
1124 
1125     // Check if a change in Rate is required.
1126     if (send_codec.rate != send_codec_inst_.rate) {
1127       if (codecs_[codec_id]->SetBitRate(send_codec.rate) < 0) {
1128         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1129                      "Could not change the codec rate.");
1130         return -1;
1131       }
1132       send_codec_inst_.rate = send_codec.rate;
1133     }
1134 
1135     if (!codecs_[codec_id]->HasInternalFEC()) {
1136       codec_fec_enabled_ = false;
1137     } else {
1138       if (codecs_[codec_id]->SetFEC(codec_fec_enabled_) < 0) {
1139         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1140                      "Cannot set codec FEC");
1141         return -1;
1142       }
1143     }
1144 
1145     previous_pltype_ = send_codec_inst_.pltype;
1146     return 0;
1147   }
1148 }
1149 
1150 // Get current send codec.
SendCodec(CodecInst * current_codec) const1151 int AudioCodingModuleImpl::SendCodec(
1152     CodecInst* current_codec) const {
1153   WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
1154                "SendCodec()");
1155   CriticalSectionScoped lock(acm_crit_sect_);
1156 
1157   if (!send_codec_registered_) {
1158     WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
1159                  "SendCodec Failed, no codec is registered");
1160     return -1;
1161   }
1162   WebRtcACMCodecParams encoder_param;
1163   codecs_[current_send_codec_idx_]->EncoderParams(&encoder_param);
1164   encoder_param.codec_inst.pltype = send_codec_inst_.pltype;
1165   memcpy(current_codec, &(encoder_param.codec_inst), sizeof(CodecInst));
1166 
1167   return 0;
1168 }
1169 
1170 // Get current send frequency.
SendFrequency() const1171 int AudioCodingModuleImpl::SendFrequency() const {
1172   WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
1173                "SendFrequency()");
1174   CriticalSectionScoped lock(acm_crit_sect_);
1175 
1176   if (!send_codec_registered_) {
1177     WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
1178                  "SendFrequency Failed, no codec is registered");
1179     return -1;
1180   }
1181 
1182   return send_codec_inst_.plfreq;
1183 }
1184 
1185 // Get encode bitrate.
1186 // Adaptive rate codecs return their current encode target rate, while other
1187 // codecs return there longterm avarage or their fixed rate.
SendBitrate() const1188 int AudioCodingModuleImpl::SendBitrate() const {
1189   CriticalSectionScoped lock(acm_crit_sect_);
1190 
1191   if (!send_codec_registered_) {
1192     WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
1193                  "SendBitrate Failed, no codec is registered");
1194     return -1;
1195   }
1196 
1197   WebRtcACMCodecParams encoder_param;
1198   codecs_[current_send_codec_idx_]->EncoderParams(&encoder_param);
1199 
1200   return encoder_param.codec_inst.rate;
1201 }
1202 
1203 // Set available bandwidth, inform the encoder about the estimated bandwidth
1204 // received from the remote party.
SetReceivedEstimatedBandwidth(int bw)1205 int AudioCodingModuleImpl::SetReceivedEstimatedBandwidth(int bw) {
1206   CriticalSectionScoped lock(acm_crit_sect_);
1207   return codecs_[current_send_codec_idx_]->SetEstimatedBandwidth(bw);
1208 }
1209 
1210 // Register a transport callback which will be called to deliver
1211 // the encoded buffers.
RegisterTransportCallback(AudioPacketizationCallback * transport)1212 int AudioCodingModuleImpl::RegisterTransportCallback(
1213     AudioPacketizationCallback* transport) {
1214   CriticalSectionScoped lock(callback_crit_sect_);
1215   packetization_callback_ = transport;
1216   return 0;
1217 }
1218 
1219 // Add 10MS of raw (PCM) audio data to the encoder.
Add10MsData(const AudioFrame & audio_frame)1220 int AudioCodingModuleImpl::Add10MsData(
1221     const AudioFrame& audio_frame) {
1222   if (audio_frame.samples_per_channel_ <= 0) {
1223     assert(false);
1224     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1225                  "Cannot Add 10 ms audio, payload length is negative or "
1226                  "zero");
1227     return -1;
1228   }
1229 
1230   if (audio_frame.sample_rate_hz_ > 48000) {
1231     assert(false);
1232     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1233                  "Cannot Add 10 ms audio, input frequency not valid");
1234     return -1;
1235   }
1236 
1237   // If the length and frequency matches. We currently just support raw PCM.
1238   if ((audio_frame.sample_rate_hz_ / 100)
1239       != audio_frame.samples_per_channel_) {
1240     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1241                  "Cannot Add 10 ms audio, input frequency and length doesn't"
1242                  " match");
1243     return -1;
1244   }
1245 
1246   if (audio_frame.num_channels_ != 1 && audio_frame.num_channels_ != 2) {
1247     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1248                  "Cannot Add 10 ms audio, invalid number of channels.");
1249     return -1;
1250   }
1251 
1252   CriticalSectionScoped lock(acm_crit_sect_);
1253   // Do we have a codec registered?
1254   if (!HaveValidEncoder("Add10MsData")) {
1255     return -1;
1256   }
1257 
1258   const AudioFrame* ptr_frame;
1259   // Perform a resampling, also down-mix if it is required and can be
1260   // performed before resampling (a down mix prior to resampling will take
1261   // place if both primary and secondary encoders are mono and input is in
1262   // stereo).
1263   if (PreprocessToAddData(audio_frame, &ptr_frame) < 0) {
1264     return -1;
1265   }
1266 
1267   // Check whether we need an up-mix or down-mix?
1268   bool remix = ptr_frame->num_channels_ != send_codec_inst_.channels;
1269   if (secondary_encoder_.get() != NULL) {
1270     remix = remix ||
1271         (ptr_frame->num_channels_ != secondary_send_codec_inst_.channels);
1272   }
1273 
1274   // If a re-mix is required (up or down), this buffer will store re-mixed
1275   // version of the input.
1276   int16_t buffer[WEBRTC_10MS_PCM_AUDIO];
1277   if (remix) {
1278     if (ptr_frame->num_channels_ == 1) {
1279       if (UpMix(*ptr_frame, WEBRTC_10MS_PCM_AUDIO, buffer) < 0)
1280         return -1;
1281     } else {
1282       if (DownMix(*ptr_frame, WEBRTC_10MS_PCM_AUDIO, buffer) < 0)
1283         return -1;
1284     }
1285   }
1286 
1287   // When adding data to encoders this pointer is pointing to an audio buffer
1288   // with correct number of channels.
1289   const int16_t* ptr_audio = ptr_frame->data_;
1290 
1291   // For pushing data to primary, point the |ptr_audio| to correct buffer.
1292   if (send_codec_inst_.channels != ptr_frame->num_channels_)
1293     ptr_audio = buffer;
1294 
1295   if (codecs_[current_send_codec_idx_]->Add10MsData(
1296       ptr_frame->timestamp_, ptr_audio, ptr_frame->samples_per_channel_,
1297       send_codec_inst_.channels) < 0)
1298     return -1;
1299 
1300   if (secondary_encoder_.get() != NULL) {
1301     // For pushing data to secondary, point the |ptr_audio| to correct buffer.
1302     ptr_audio = ptr_frame->data_;
1303     if (secondary_send_codec_inst_.channels != ptr_frame->num_channels_)
1304       ptr_audio = buffer;
1305 
1306     if (secondary_encoder_->Add10MsData(
1307         ptr_frame->timestamp_, ptr_audio, ptr_frame->samples_per_channel_,
1308         secondary_send_codec_inst_.channels) < 0)
1309       return -1;
1310   }
1311 
1312   return 0;
1313 }
1314 
1315 // Perform a resampling and down-mix if required. We down-mix only if
1316 // encoder is mono and input is stereo. In case of dual-streaming, both
1317 // encoders has to be mono for down-mix to take place.
1318 // |*ptr_out| will point to the pre-processed audio-frame. If no pre-processing
1319 // is required, |*ptr_out| points to |in_frame|.
PreprocessToAddData(const AudioFrame & in_frame,const AudioFrame ** ptr_out)1320 int AudioCodingModuleImpl::PreprocessToAddData(const AudioFrame& in_frame,
1321                                                const AudioFrame** ptr_out) {
1322   // Primary and secondary (if exists) should have the same sampling rate.
1323   assert((secondary_encoder_.get() != NULL) ?
1324       secondary_send_codec_inst_.plfreq == send_codec_inst_.plfreq : true);
1325 
1326   bool resample = (in_frame.sample_rate_hz_ != send_codec_inst_.plfreq);
1327 
1328   // This variable is true if primary codec and secondary codec (if exists)
1329   // are both mono and input is stereo.
1330   bool down_mix;
1331   if (secondary_encoder_.get() != NULL) {
1332     down_mix = (in_frame.num_channels_ == 2) &&
1333         (send_codec_inst_.channels == 1) &&
1334         (secondary_send_codec_inst_.channels == 1);
1335   } else {
1336     down_mix = (in_frame.num_channels_ == 2) &&
1337         (send_codec_inst_.channels == 1);
1338   }
1339 
1340   if (!first_10ms_data_) {
1341     expected_in_ts_ = in_frame.timestamp_;
1342     expected_codec_ts_ = in_frame.timestamp_;
1343     first_10ms_data_ = true;
1344   } else if (in_frame.timestamp_ != expected_in_ts_) {
1345     // TODO(turajs): Do we need a warning here.
1346     expected_codec_ts_ += (in_frame.timestamp_ - expected_in_ts_) *
1347         static_cast<uint32_t>((static_cast<double>(send_codec_inst_.plfreq) /
1348                     static_cast<double>(in_frame.sample_rate_hz_)));
1349     expected_in_ts_ = in_frame.timestamp_;
1350   }
1351 
1352 
1353   if (!down_mix && !resample) {
1354     // No pre-processing is required.
1355     expected_in_ts_ += in_frame.samples_per_channel_;
1356     expected_codec_ts_ += in_frame.samples_per_channel_;
1357     *ptr_out = &in_frame;
1358     return 0;
1359   }
1360 
1361   *ptr_out = &preprocess_frame_;
1362   preprocess_frame_.num_channels_ = in_frame.num_channels_;
1363   int16_t audio[WEBRTC_10MS_PCM_AUDIO];
1364   const int16_t* src_ptr_audio = in_frame.data_;
1365   int16_t* dest_ptr_audio = preprocess_frame_.data_;
1366   if (down_mix) {
1367     // If a resampling is required the output of a down-mix is written into a
1368     // local buffer, otherwise, it will be written to the output frame.
1369     if (resample)
1370       dest_ptr_audio = audio;
1371     if (DownMix(in_frame, WEBRTC_10MS_PCM_AUDIO, dest_ptr_audio) < 0)
1372       return -1;
1373     preprocess_frame_.num_channels_ = 1;
1374     // Set the input of the resampler is the down-mixed signal.
1375     src_ptr_audio = audio;
1376   }
1377 
1378   preprocess_frame_.timestamp_ = expected_codec_ts_;
1379   preprocess_frame_.samples_per_channel_ = in_frame.samples_per_channel_;
1380   preprocess_frame_.sample_rate_hz_ = in_frame.sample_rate_hz_;
1381   // If it is required, we have to do a resampling.
1382   if (resample) {
1383     // The result of the resampler is written to output frame.
1384     dest_ptr_audio = preprocess_frame_.data_;
1385 
1386     preprocess_frame_.samples_per_channel_ =
1387         resampler_.Resample10Msec(src_ptr_audio,
1388                                   in_frame.sample_rate_hz_,
1389                                   send_codec_inst_.plfreq,
1390                                   preprocess_frame_.num_channels_,
1391                                   AudioFrame::kMaxDataSizeSamples,
1392                                   dest_ptr_audio);
1393 
1394     if (preprocess_frame_.samples_per_channel_ < 0) {
1395       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1396                    "Cannot add 10 ms audio, resampling failed");
1397       return -1;
1398     }
1399     preprocess_frame_.sample_rate_hz_ = send_codec_inst_.plfreq;
1400   }
1401 
1402   expected_codec_ts_ += preprocess_frame_.samples_per_channel_;
1403   expected_in_ts_ += in_frame.samples_per_channel_;
1404 
1405   return 0;
1406 }
1407 
1408 /////////////////////////////////////////
1409 //   (RED) Redundant Coding
1410 //
1411 
REDStatus() const1412 bool AudioCodingModuleImpl::REDStatus() const {
1413   CriticalSectionScoped lock(acm_crit_sect_);
1414 
1415   return red_enabled_;
1416 }
1417 
1418 // Configure RED status i.e on/off.
SetREDStatus(bool enable_red)1419 int AudioCodingModuleImpl::SetREDStatus(
1420 #ifdef WEBRTC_CODEC_RED
1421     bool enable_red) {
1422   CriticalSectionScoped lock(acm_crit_sect_);
1423 
1424   if (enable_red == true && codec_fec_enabled_ == true) {
1425     WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
1426                  "Codec internal FEC and RED cannot be co-enabled.");
1427     return -1;
1428   }
1429 
1430   if (red_enabled_ != enable_red) {
1431     // Reset the RED buffer.
1432     memset(red_buffer_, 0, MAX_PAYLOAD_SIZE_BYTE);
1433 
1434     // Reset fragmentation buffers.
1435     ResetFragmentation(kNumRedFragmentationVectors);
1436     // Set red_enabled_.
1437     red_enabled_ = enable_red;
1438   }
1439   is_first_red_ = true;  // Make sure we restart RED.
1440   return 0;
1441 #else
1442     bool /* enable_red */) {
1443   red_enabled_ = false;
1444   WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
1445                "  WEBRTC_CODEC_RED is undefined => red_enabled_ = %d",
1446                red_enabled_);
1447   return -1;
1448 #endif
1449 }
1450 
1451 /////////////////////////////////////////
1452 //   (FEC) Forward Error Correction (codec internal)
1453 //
1454 
1455 bool AudioCodingModuleImpl::CodecFEC() const {
1456   CriticalSectionScoped lock(acm_crit_sect_);
1457   return codec_fec_enabled_;
1458 }
1459 
1460 int AudioCodingModuleImpl::SetCodecFEC(bool enable_codec_fec) {
1461   CriticalSectionScoped lock(acm_crit_sect_);
1462 
1463   if (enable_codec_fec == true && red_enabled_ == true) {
1464     WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
1465                  "Codec internal FEC and RED cannot be co-enabled.");
1466     return -1;
1467   }
1468 
1469   // Set codec FEC.
1470   if (HaveValidEncoder("SetCodecFEC") &&
1471       codecs_[current_send_codec_idx_]->SetFEC(enable_codec_fec) < 0) {
1472       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1473                    "Set codec internal FEC failed.");
1474     return -1;
1475   }
1476   codec_fec_enabled_ = enable_codec_fec;
1477   return 0;
1478 }
1479 
1480 int AudioCodingModuleImpl::SetPacketLossRate(int loss_rate) {
1481   CriticalSectionScoped lock(acm_crit_sect_);
1482   if (HaveValidEncoder("SetPacketLossRate") &&
1483       codecs_[current_send_codec_idx_]->SetPacketLossRate(loss_rate) < 0) {
1484       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1485                    "Set packet loss rate failed.");
1486     return -1;
1487   }
1488   return 0;
1489 }
1490 
1491 /////////////////////////////////////////
1492 //   (VAD) Voice Activity Detection
1493 //
1494 int AudioCodingModuleImpl::SetVAD(bool enable_dtx,
1495                                   bool enable_vad,
1496                                   ACMVADMode mode) {
1497   CriticalSectionScoped lock(acm_crit_sect_);
1498   return SetVADSafe(enable_dtx, enable_vad, mode);
1499 }
1500 
1501 int AudioCodingModuleImpl::SetVADSafe(bool enable_dtx,
1502                                       bool enable_vad,
1503                                       ACMVADMode mode) {
1504   // Sanity check of the mode.
1505   if ((mode != VADNormal) && (mode != VADLowBitrate)
1506       && (mode != VADAggr) && (mode != VADVeryAggr)) {
1507     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1508                  "Invalid VAD Mode %d, no change is made to VAD/DTX status",
1509                  mode);
1510     return -1;
1511   }
1512 
1513   // Check that the send codec is mono. We don't support VAD/DTX for stereo
1514   // sending.
1515   if ((enable_dtx || enable_vad) && stereo_send_) {
1516     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1517                  "VAD/DTX not supported for stereo sending");
1518     dtx_enabled_ = false;
1519     vad_enabled_ = false;
1520     vad_mode_ = mode;
1521     return -1;
1522   }
1523 
1524   // We don't support VAD/DTX when dual-streaming is enabled, i.e.
1525   // secondary-encoder is registered.
1526   if ((enable_dtx || enable_vad) && secondary_encoder_.get() != NULL) {
1527     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1528                  "VAD/DTX not supported when dual-streaming is enabled.");
1529     dtx_enabled_ = false;
1530     vad_enabled_ = false;
1531     vad_mode_ = mode;
1532     return -1;
1533   }
1534 
1535   // Store VAD/DTX settings. Values can be changed in the call to "SetVAD"
1536   // below.
1537   dtx_enabled_ = enable_dtx;
1538   vad_enabled_ = enable_vad;
1539   vad_mode_ = mode;
1540 
1541   // If a send codec is registered, set VAD/DTX for the codec.
1542   if (HaveValidEncoder("SetVAD") && codecs_[current_send_codec_idx_]->SetVAD(
1543       &dtx_enabled_, &vad_enabled_,  &vad_mode_) < 0) {
1544       // SetVAD failed.
1545       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1546                    "SetVAD failed");
1547       vad_enabled_ = false;
1548       dtx_enabled_ = false;
1549       return -1;
1550   }
1551   return 0;
1552 }
1553 
1554 // Get VAD/DTX settings.
1555 int AudioCodingModuleImpl::VAD(bool* dtx_enabled, bool* vad_enabled,
1556                                ACMVADMode* mode) const {
1557   CriticalSectionScoped lock(acm_crit_sect_);
1558 
1559   *dtx_enabled = dtx_enabled_;
1560   *vad_enabled = vad_enabled_;
1561   *mode = vad_mode_;
1562 
1563   return 0;
1564 }
1565 
1566 /////////////////////////////////////////
1567 //   Receiver
1568 //
1569 
1570 int AudioCodingModuleImpl::InitializeReceiver() {
1571   CriticalSectionScoped lock(acm_crit_sect_);
1572   return InitializeReceiverSafe();
1573 }
1574 
1575 // Initialize receiver, resets codec database etc.
1576 int AudioCodingModuleImpl::InitializeReceiverSafe() {
1577   // If the receiver is already initialized then we want to destroy any
1578   // existing decoders. After a call to this function, we should have a clean
1579   // start-up.
1580   if (receiver_initialized_) {
1581     if (receiver_.RemoveAllCodecs() < 0)
1582       return -1;
1583   }
1584   receiver_.set_id(id_);
1585   receiver_.ResetInitialDelay();
1586   receiver_.SetMinimumDelay(0);
1587   receiver_.SetMaximumDelay(0);
1588   receiver_.FlushBuffers();
1589 
1590   // Register RED and CN.
1591   for (int i = 0; i < ACMCodecDB::kNumCodecs; i++) {
1592     if (IsCodecRED(i) || IsCodecCN(i)) {
1593       uint8_t pl_type = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
1594       if (receiver_.AddCodec(i, pl_type, 1, NULL) < 0) {
1595         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1596                      "Cannot register master codec.");
1597         return -1;
1598       }
1599     }
1600   }
1601   receiver_initialized_ = true;
1602   return 0;
1603 }
1604 
1605 // TODO(turajs): If NetEq opens an API for reseting the state of decoders then
1606 // implement this method. Otherwise it should be removed. I might be that by
1607 // removing and registering a decoder we can achieve the effect of resetting.
1608 // Reset the decoder state.
1609 int AudioCodingModuleImpl::ResetDecoder() {
1610   return 0;
1611 }
1612 
1613 // Get current receive frequency.
1614 int AudioCodingModuleImpl::ReceiveFrequency() const {
1615   WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
1616                "ReceiveFrequency()");
1617 
1618   CriticalSectionScoped lock(acm_crit_sect_);
1619 
1620   int codec_id = receiver_.last_audio_codec_id();
1621 
1622   return codec_id < 0 ? receiver_.current_sample_rate_hz() :
1623                         ACMCodecDB::database_[codec_id].plfreq;
1624 }
1625 
1626 // Get current playout frequency.
1627 int AudioCodingModuleImpl::PlayoutFrequency() const {
1628   WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
1629                "PlayoutFrequency()");
1630 
1631   CriticalSectionScoped lock(acm_crit_sect_);
1632 
1633   return receiver_.current_sample_rate_hz();
1634 }
1635 
1636 // Register possible receive codecs, can be called multiple times,
1637 // for codecs, CNG (NB, WB and SWB), DTMF, RED.
1638 int AudioCodingModuleImpl::RegisterReceiveCodec(const CodecInst& codec) {
1639   CriticalSectionScoped lock(acm_crit_sect_);
1640 
1641   if (codec.channels > 2 || codec.channels < 0) {
1642     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1643                  "Unsupported number of channels, %d.", codec.channels);
1644     return -1;
1645   }
1646 
1647   // TODO(turajs) do we need this for NetEq 4?
1648   if (!receiver_initialized_) {
1649     if (InitializeReceiverSafe() < 0) {
1650       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1651                    "Cannot initialize receiver, failed registering codec.");
1652       return -1;
1653     }
1654   }
1655 
1656   int mirror_id;
1657   int codec_id = ACMCodecDB::ReceiverCodecNumber(codec, &mirror_id);
1658 
1659   if (codec_id < 0 || codec_id >= ACMCodecDB::kNumCodecs) {
1660     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1661                  "Wrong codec params to be registered as receive codec");
1662     return -1;
1663   }
1664 
1665   // Check if the payload-type is valid.
1666   if (!ACMCodecDB::ValidPayloadType(codec.pltype)) {
1667     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1668                  "Invalid payload-type %d for %s.", codec.pltype,
1669                  codec.plname);
1670     return -1;
1671   }
1672 
1673   AudioDecoder* decoder = NULL;
1674   // Get |decoder| associated with |codec|. |decoder| can be NULL if |codec|
1675   // does not own its decoder.
1676   if (GetAudioDecoder(codec, codec_id, mirror_id, &decoder) < 0) {
1677     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1678                  "Wrong codec params to be registered as receive codec");
1679     return -1;
1680   }
1681   uint8_t payload_type = static_cast<uint8_t>(codec.pltype);
1682   return receiver_.AddCodec(codec_id, payload_type, codec.channels, decoder);
1683 }
1684 
1685 // Get current received codec.
1686 int AudioCodingModuleImpl::ReceiveCodec(CodecInst* current_codec) const {
1687   return receiver_.LastAudioCodec(current_codec);
1688 }
1689 
1690 // Incoming packet from network parsed and ready for decode.
1691 int AudioCodingModuleImpl::IncomingPacket(const uint8_t* incoming_payload,
1692                                           const int payload_length,
1693                                           const WebRtcRTPHeader& rtp_header) {
1694   if (payload_length < 0) {
1695     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1696                  "IncomingPacket() Error, payload-length cannot be negative");
1697     return -1;
1698   }
1699   int last_audio_pltype = receiver_.last_audio_payload_type();
1700   if (receiver_.InsertPacket(rtp_header, incoming_payload, payload_length) <
1701       0) {
1702     return -1;
1703   }
1704   if (receiver_.last_audio_payload_type() != last_audio_pltype) {
1705     int index = receiver_.last_audio_codec_id();
1706     assert(index >= 0);
1707     CriticalSectionScoped lock(acm_crit_sect_);
1708 
1709     // |codec_[index]| might not be even created, simply because it is not
1710     // yet registered as send codec. Even if it is registered, unless the
1711     // codec shares same instance for encoder and decoder, this call is
1712     // useless.
1713     if (codecs_[index] != NULL)
1714       codecs_[index]->UpdateDecoderSampFreq(index);
1715   }
1716   return 0;
1717 }
1718 
1719 // Minimum playout delay (Used for lip-sync).
1720 int AudioCodingModuleImpl::SetMinimumPlayoutDelay(int time_ms) {
1721   if ((time_ms < 0) || (time_ms > 10000)) {
1722     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1723                  "Delay must be in the range of 0-1000 milliseconds.");
1724     return -1;
1725   }
1726   return receiver_.SetMinimumDelay(time_ms);
1727 }
1728 
1729 int AudioCodingModuleImpl::SetMaximumPlayoutDelay(int time_ms) {
1730   if ((time_ms < 0) || (time_ms > 10000)) {
1731     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1732                  "Delay must be in the range of 0-1000 milliseconds.");
1733     return -1;
1734   }
1735   return receiver_.SetMaximumDelay(time_ms);
1736 }
1737 
1738 // Estimate the Bandwidth based on the incoming stream, needed for one way
1739 // audio where the RTCP send the BW estimate.
1740 // This is also done in the RTP module.
1741 int AudioCodingModuleImpl::DecoderEstimatedBandwidth() const {
1742   // We can estimate far-end to near-end bandwidth if the iSAC are sent. Check
1743   // if the last received packets were iSAC packet then retrieve the bandwidth.
1744   int last_audio_codec_id = receiver_.last_audio_codec_id();
1745   if (last_audio_codec_id >= 0 &&
1746       STR_CASE_CMP("ISAC", ACMCodecDB::database_[last_audio_codec_id].plname)) {
1747     CriticalSectionScoped lock(acm_crit_sect_);
1748     return codecs_[last_audio_codec_id]->GetEstimatedBandwidth();
1749   }
1750   return -1;
1751 }
1752 
1753 // Set playout mode for: voice, fax, streaming or off.
1754 int AudioCodingModuleImpl::SetPlayoutMode(AudioPlayoutMode mode) {
1755   receiver_.SetPlayoutMode(mode);
1756   return 0;  // TODO(turajs): return value is for backward compatibility.
1757 }
1758 
1759 // Get playout mode voice, fax, streaming or off.
1760 AudioPlayoutMode AudioCodingModuleImpl::PlayoutMode() const {
1761   return receiver_.PlayoutMode();
1762 }
1763 
1764 // Get 10 milliseconds of raw audio data to play out.
1765 // Automatic resample to the requested frequency.
1766 int AudioCodingModuleImpl::PlayoutData10Ms(int desired_freq_hz,
1767                                            AudioFrame* audio_frame) {
1768   // GetAudio always returns 10 ms, at the requested sample rate.
1769   if (receiver_.GetAudio(desired_freq_hz, audio_frame) != 0) {
1770     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1771                  "PlayoutData failed, RecOut Failed");
1772     return -1;
1773   }
1774 
1775   audio_frame->id_ = id_;
1776   return 0;
1777 }
1778 
1779 /////////////////////////////////////////
1780 //   Statistics
1781 //
1782 
1783 // TODO(turajs) change the return value to void. Also change the corresponding
1784 // NetEq function.
1785 int AudioCodingModuleImpl::NetworkStatistics(ACMNetworkStatistics* statistics) {
1786   receiver_.NetworkStatistics(statistics);
1787   return 0;
1788 }
1789 
1790 int AudioCodingModuleImpl::RegisterVADCallback(ACMVADCallback* vad_callback) {
1791   WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, id_,
1792                "RegisterVADCallback()");
1793   CriticalSectionScoped lock(callback_crit_sect_);
1794   vad_callback_ = vad_callback;
1795   return 0;
1796 }
1797 
1798 // TODO(tlegrand): Modify this function to work for stereo, and add tests.
1799 int AudioCodingModuleImpl::IncomingPayload(const uint8_t* incoming_payload,
1800                                            int payload_length,
1801                                            uint8_t payload_type,
1802                                            uint32_t timestamp) {
1803   if (payload_length < 0) {
1804     // Log error in trace file.
1805     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1806                  "IncomingPacket() Error, payload-length cannot be negative");
1807     return -1;
1808   }
1809 
1810   // We are not acquiring any lock when interacting with |aux_rtp_header_| no
1811   // other method uses this member variable.
1812   if (aux_rtp_header_ == NULL) {
1813     // This is the first time that we are using |dummy_rtp_header_|
1814     // so we have to create it.
1815     aux_rtp_header_ = new WebRtcRTPHeader;
1816     aux_rtp_header_->header.payloadType = payload_type;
1817     // Don't matter in this case.
1818     aux_rtp_header_->header.ssrc = 0;
1819     aux_rtp_header_->header.markerBit = false;
1820     // Start with random numbers.
1821     aux_rtp_header_->header.sequenceNumber = 0x1234;  // Arbitrary.
1822     aux_rtp_header_->type.Audio.channel = 1;
1823   }
1824 
1825   aux_rtp_header_->header.timestamp = timestamp;
1826   IncomingPacket(incoming_payload, payload_length, *aux_rtp_header_);
1827   // Get ready for the next payload.
1828   aux_rtp_header_->header.sequenceNumber++;
1829   return 0;
1830 }
1831 
1832 int AudioCodingModuleImpl::ReplaceInternalDTXWithWebRtc(bool use_webrtc_dtx) {
1833   CriticalSectionScoped lock(acm_crit_sect_);
1834 
1835   if (!HaveValidEncoder("ReplaceInternalDTXWithWebRtc")) {
1836     WEBRTC_TRACE(
1837         webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1838         "Cannot replace codec internal DTX when no send codec is registered.");
1839     return -1;
1840   }
1841 
1842   int res = codecs_[current_send_codec_idx_]->ReplaceInternalDTX(
1843       use_webrtc_dtx);
1844   // Check if VAD is turned on, or if there is any error.
1845   if (res == 1) {
1846     vad_enabled_ = true;
1847   } else if (res < 0) {
1848     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1849                  "Failed to set ReplaceInternalDTXWithWebRtc(%d)",
1850                  use_webrtc_dtx);
1851     return res;
1852   }
1853 
1854   return 0;
1855 }
1856 
1857 int AudioCodingModuleImpl::IsInternalDTXReplacedWithWebRtc(
1858     bool* uses_webrtc_dtx) {
1859   CriticalSectionScoped lock(acm_crit_sect_);
1860 
1861   if (!HaveValidEncoder("IsInternalDTXReplacedWithWebRtc")) {
1862     return -1;
1863   }
1864   if (codecs_[current_send_codec_idx_]->IsInternalDTXReplaced(uses_webrtc_dtx)
1865       < 0) {
1866     return -1;
1867   }
1868   return 0;
1869 }
1870 
1871 int AudioCodingModuleImpl::SetISACMaxRate(int max_bit_per_sec) {
1872   CriticalSectionScoped lock(acm_crit_sect_);
1873 
1874   if (!HaveValidEncoder("SetISACMaxRate")) {
1875     return -1;
1876   }
1877 
1878   return codecs_[current_send_codec_idx_]->SetISACMaxRate(max_bit_per_sec);
1879 }
1880 
1881 int AudioCodingModuleImpl::SetISACMaxPayloadSize(int max_size_bytes) {
1882   CriticalSectionScoped lock(acm_crit_sect_);
1883 
1884   if (!HaveValidEncoder("SetISACMaxPayloadSize")) {
1885     return -1;
1886   }
1887 
1888   return codecs_[current_send_codec_idx_]->SetISACMaxPayloadSize(
1889       max_size_bytes);
1890 }
1891 
1892 int AudioCodingModuleImpl::ConfigISACBandwidthEstimator(
1893     int frame_size_ms,
1894     int rate_bit_per_sec,
1895     bool enforce_frame_size) {
1896   CriticalSectionScoped lock(acm_crit_sect_);
1897 
1898   if (!HaveValidEncoder("ConfigISACBandwidthEstimator")) {
1899     return -1;
1900   }
1901 
1902   return codecs_[current_send_codec_idx_]->ConfigISACBandwidthEstimator(
1903       frame_size_ms, rate_bit_per_sec, enforce_frame_size);
1904 }
1905 
1906 // Informs Opus encoder of the maximum playback rate the receiver will render.
1907 int AudioCodingModuleImpl::SetOpusMaxPlaybackRate(int frequency_hz) {
1908   CriticalSectionScoped lock(acm_crit_sect_);
1909   if (!HaveValidEncoder("SetOpusMaxPlaybackRate")) {
1910     return -1;
1911   }
1912   return codecs_[current_send_codec_idx_]->SetOpusMaxPlaybackRate(frequency_hz);
1913 }
1914 
1915 int AudioCodingModuleImpl::PlayoutTimestamp(uint32_t* timestamp) {
1916   return receiver_.GetPlayoutTimestamp(timestamp) ? 0 : -1;
1917 }
1918 
1919 bool AudioCodingModuleImpl::HaveValidEncoder(const char* caller_name) const {
1920   if ((!send_codec_registered_) || (current_send_codec_idx_ < 0) ||
1921       (current_send_codec_idx_ >= ACMCodecDB::kNumCodecs)) {
1922     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1923                  "%s failed: No send codec is registered.", caller_name);
1924     return false;
1925   }
1926   if ((current_send_codec_idx_ < 0) ||
1927       (current_send_codec_idx_ >= ACMCodecDB::kNumCodecs)) {
1928     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1929                  "%s failed: Send codec index out of range.", caller_name);
1930     return false;
1931   }
1932   if (codecs_[current_send_codec_idx_] == NULL) {
1933     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1934                  "%s failed: Send codec is NULL pointer.", caller_name);
1935     return false;
1936   }
1937   return true;
1938 }
1939 
1940 int AudioCodingModuleImpl::UnregisterReceiveCodec(uint8_t payload_type) {
1941   return receiver_.RemoveCodec(payload_type);
1942 }
1943 
1944 // TODO(turajs): correct the type of |length_bytes| when it is corrected in
1945 // GenericCodec.
1946 int AudioCodingModuleImpl::REDPayloadISAC(int isac_rate,
1947                                           int isac_bw_estimate,
1948                                           uint8_t* payload,
1949                                           int16_t* length_bytes) {
1950   CriticalSectionScoped lock(acm_crit_sect_);
1951   if (!HaveValidEncoder("EncodeData")) {
1952     return -1;
1953   }
1954   int status;
1955   status = codecs_[current_send_codec_idx_]->REDPayloadISAC(isac_rate,
1956                                                             isac_bw_estimate,
1957                                                             payload,
1958                                                             length_bytes);
1959   return status;
1960 }
1961 
1962 void AudioCodingModuleImpl::ResetFragmentation(int vector_size) {
1963   for (int n = 0; n < kMaxNumFragmentationVectors; n++) {
1964     fragmentation_.fragmentationOffset[n] = n * MAX_PAYLOAD_SIZE_BYTE;
1965   }
1966   memset(fragmentation_.fragmentationLength, 0, kMaxNumFragmentationVectors *
1967          sizeof(fragmentation_.fragmentationLength[0]));
1968   memset(fragmentation_.fragmentationTimeDiff, 0, kMaxNumFragmentationVectors *
1969          sizeof(fragmentation_.fragmentationTimeDiff[0]));
1970   memset(fragmentation_.fragmentationPlType,
1971          0,
1972          kMaxNumFragmentationVectors *
1973              sizeof(fragmentation_.fragmentationPlType[0]));
1974   fragmentation_.fragmentationVectorSize = static_cast<uint16_t>(vector_size);
1975 }
1976 
1977 int AudioCodingModuleImpl::GetAudioDecoder(const CodecInst& codec, int codec_id,
1978                                            int mirror_id,
1979                                            AudioDecoder** decoder) {
1980   if (ACMCodecDB::OwnsDecoder(codec_id)) {
1981     // This codec has to own its own decoder. Therefore, it should create the
1982     // corresponding AudioDecoder class and insert it into NetEq. If the codec
1983     // does not exist create it.
1984     //
1985     // TODO(turajs): this part of the code is common with RegisterSendCodec(),
1986     //               make a method for it.
1987     if (codecs_[mirror_id] == NULL) {
1988       codecs_[mirror_id] = CreateCodec(codec);
1989       if (codecs_[mirror_id] == NULL) {
1990         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
1991                      "Cannot Create the codec");
1992         return -1;
1993       }
1994       mirror_codec_idx_[mirror_id] = mirror_id;
1995     }
1996 
1997     if (mirror_id != codec_id) {
1998       codecs_[codec_id] = codecs_[mirror_id];
1999       mirror_codec_idx_[codec_id] = mirror_id;
2000     }
2001     *decoder = codecs_[codec_id]->Decoder(codec_id);
2002     if (!*decoder) {
2003       assert(false);
2004       return -1;
2005     }
2006   } else {
2007     *decoder = NULL;
2008   }
2009 
2010   return 0;
2011 }
2012 
2013 int AudioCodingModuleImpl::SetInitialPlayoutDelay(int delay_ms) {
2014   {
2015     CriticalSectionScoped lock(acm_crit_sect_);
2016     // Initialize receiver, if it is not initialized. Otherwise, initial delay
2017     // is reset upon initialization of the receiver.
2018     if (!receiver_initialized_)
2019       InitializeReceiverSafe();
2020   }
2021   return receiver_.SetInitialDelay(delay_ms);
2022 }
2023 
2024 int AudioCodingModuleImpl::EnableNack(size_t max_nack_list_size) {
2025   return receiver_.EnableNack(max_nack_list_size);
2026 }
2027 
2028 void AudioCodingModuleImpl::DisableNack() {
2029   receiver_.DisableNack();
2030 }
2031 
2032 std::vector<uint16_t> AudioCodingModuleImpl::GetNackList(
2033     int round_trip_time_ms) const {
2034   return receiver_.GetNackList(round_trip_time_ms);
2035 }
2036 
2037 int AudioCodingModuleImpl::LeastRequiredDelayMs() const {
2038   return receiver_.LeastRequiredDelayMs();
2039 }
2040 
2041 void AudioCodingModuleImpl::GetDecodingCallStatistics(
2042       AudioDecodingCallStats* call_stats) const {
2043   receiver_.GetDecodingCallStatistics(call_stats);
2044 }
2045 
2046 }  // namespace acm2
2047 
RegisterSendCodec(AudioEncoder * send_codec)2048 bool AudioCodingImpl::RegisterSendCodec(AudioEncoder* send_codec) {
2049   FATAL() << "Not implemented yet.";
2050 }
2051 
RegisterSendCodec(int encoder_type,uint8_t payload_type,int frame_size_samples)2052 bool AudioCodingImpl::RegisterSendCodec(int encoder_type,
2053                                         uint8_t payload_type,
2054                                         int frame_size_samples) {
2055   std::string codec_name;
2056   int sample_rate_hz;
2057   int channels;
2058   if (!MapCodecTypeToParameters(
2059           encoder_type, &codec_name, &sample_rate_hz, &channels)) {
2060     return false;
2061   }
2062   webrtc::CodecInst codec;
2063   AudioCodingModule::Codec(
2064       codec_name.c_str(), &codec, sample_rate_hz, channels);
2065   codec.pltype = payload_type;
2066   if (frame_size_samples > 0) {
2067     codec.pacsize = frame_size_samples;
2068   }
2069   return acm_old_->RegisterSendCodec(codec) == 0;
2070 }
2071 
GetSenderInfo() const2072 const AudioEncoder* AudioCodingImpl::GetSenderInfo() const {
2073   FATAL() << "Not implemented yet.";
2074 }
2075 
GetSenderCodecInst()2076 const CodecInst* AudioCodingImpl::GetSenderCodecInst() {
2077   if (acm_old_->SendCodec(&current_send_codec_) != 0) {
2078     return NULL;
2079   }
2080   return &current_send_codec_;
2081 }
2082 
Add10MsAudio(const AudioFrame & audio_frame)2083 int AudioCodingImpl::Add10MsAudio(const AudioFrame& audio_frame) {
2084   if (acm_old_->Add10MsData(audio_frame) != 0) {
2085     return -1;
2086   }
2087   return acm_old_->Process();
2088 }
2089 
GetReceiverInfo() const2090 const ReceiverInfo* AudioCodingImpl::GetReceiverInfo() const {
2091   FATAL() << "Not implemented yet.";
2092 }
2093 
RegisterReceiveCodec(AudioDecoder * receive_codec)2094 bool AudioCodingImpl::RegisterReceiveCodec(AudioDecoder* receive_codec) {
2095   FATAL() << "Not implemented yet.";
2096 }
2097 
RegisterReceiveCodec(int decoder_type,uint8_t payload_type)2098 bool AudioCodingImpl::RegisterReceiveCodec(int decoder_type,
2099                                            uint8_t payload_type) {
2100   std::string codec_name;
2101   int sample_rate_hz;
2102   int channels;
2103   if (!MapCodecTypeToParameters(
2104           decoder_type, &codec_name, &sample_rate_hz, &channels)) {
2105     return false;
2106   }
2107   webrtc::CodecInst codec;
2108   AudioCodingModule::Codec(
2109       codec_name.c_str(), &codec, sample_rate_hz, channels);
2110   codec.pltype = payload_type;
2111   return acm_old_->RegisterReceiveCodec(codec) == 0;
2112 }
2113 
InsertPacket(const uint8_t * incoming_payload,int32_t payload_len_bytes,const WebRtcRTPHeader & rtp_info)2114 bool AudioCodingImpl::InsertPacket(const uint8_t* incoming_payload,
2115                                    int32_t payload_len_bytes,
2116                                    const WebRtcRTPHeader& rtp_info) {
2117   return acm_old_->IncomingPacket(
2118              incoming_payload, payload_len_bytes, rtp_info) == 0;
2119 }
2120 
InsertPayload(const uint8_t * incoming_payload,int32_t payload_len_byte,uint8_t payload_type,uint32_t timestamp)2121 bool AudioCodingImpl::InsertPayload(const uint8_t* incoming_payload,
2122                                     int32_t payload_len_byte,
2123                                     uint8_t payload_type,
2124                                     uint32_t timestamp) {
2125   FATAL() << "Not implemented yet.";
2126 }
2127 
SetMinimumPlayoutDelay(int time_ms)2128 bool AudioCodingImpl::SetMinimumPlayoutDelay(int time_ms) {
2129   FATAL() << "Not implemented yet.";
2130 }
2131 
SetMaximumPlayoutDelay(int time_ms)2132 bool AudioCodingImpl::SetMaximumPlayoutDelay(int time_ms) {
2133   FATAL() << "Not implemented yet.";
2134 }
2135 
LeastRequiredDelayMs() const2136 int AudioCodingImpl::LeastRequiredDelayMs() const {
2137   FATAL() << "Not implemented yet.";
2138 }
2139 
PlayoutTimestamp(uint32_t * timestamp)2140 bool AudioCodingImpl::PlayoutTimestamp(uint32_t* timestamp) {
2141   FATAL() << "Not implemented yet.";
2142 }
2143 
Get10MsAudio(AudioFrame * audio_frame)2144 bool AudioCodingImpl::Get10MsAudio(AudioFrame* audio_frame) {
2145   return acm_old_->PlayoutData10Ms(playout_frequency_hz_, audio_frame) == 0;
2146 }
2147 
NetworkStatistics(ACMNetworkStatistics * network_statistics)2148 bool AudioCodingImpl::NetworkStatistics(
2149     ACMNetworkStatistics* network_statistics) {
2150   FATAL() << "Not implemented yet.";
2151 }
2152 
EnableNack(size_t max_nack_list_size)2153 bool AudioCodingImpl::EnableNack(size_t max_nack_list_size) {
2154   FATAL() << "Not implemented yet.";
2155 }
2156 
DisableNack()2157 void AudioCodingImpl::DisableNack() {
2158   FATAL() << "Not implemented yet.";
2159 }
2160 
SetVad(bool enable_dtx,bool enable_vad,ACMVADMode vad_mode)2161 bool AudioCodingImpl::SetVad(bool enable_dtx,
2162                              bool enable_vad,
2163                              ACMVADMode vad_mode) {
2164   return acm_old_->SetVAD(enable_dtx, enable_vad, vad_mode) == 0;
2165 }
2166 
GetNackList(int round_trip_time_ms) const2167 std::vector<uint16_t> AudioCodingImpl::GetNackList(
2168     int round_trip_time_ms) const {
2169   return acm_old_->GetNackList(round_trip_time_ms);
2170 }
2171 
GetDecodingCallStatistics(AudioDecodingCallStats * call_stats) const2172 void AudioCodingImpl::GetDecodingCallStatistics(
2173     AudioDecodingCallStats* call_stats) const {
2174   acm_old_->GetDecodingCallStatistics(call_stats);
2175 }
2176 
MapCodecTypeToParameters(int codec_type,std::string * codec_name,int * sample_rate_hz,int * channels)2177 bool AudioCodingImpl::MapCodecTypeToParameters(int codec_type,
2178                                                std::string* codec_name,
2179                                                int* sample_rate_hz,
2180                                                int* channels) {
2181   switch (codec_type) {
2182 #ifdef WEBRTC_CODEC_PCM16
2183     case acm2::ACMCodecDB::kPCM16B:
2184       *codec_name = "L16";
2185       *sample_rate_hz = 8000;
2186       *channels = 1;
2187       break;
2188     case acm2::ACMCodecDB::kPCM16Bwb:
2189       *codec_name = "L16";
2190       *sample_rate_hz = 16000;
2191       *channels = 1;
2192       break;
2193     case acm2::ACMCodecDB::kPCM16Bswb32kHz:
2194       *codec_name = "L16";
2195       *sample_rate_hz = 32000;
2196       *channels = 1;
2197       break;
2198     case acm2::ACMCodecDB::kPCM16B_2ch:
2199       *codec_name = "L16";
2200       *sample_rate_hz = 8000;
2201       *channels = 2;
2202       break;
2203     case acm2::ACMCodecDB::kPCM16Bwb_2ch:
2204       *codec_name = "L16";
2205       *sample_rate_hz = 16000;
2206       *channels = 2;
2207       break;
2208     case acm2::ACMCodecDB::kPCM16Bswb32kHz_2ch:
2209       *codec_name = "L16";
2210       *sample_rate_hz = 32000;
2211       *channels = 2;
2212       break;
2213 #endif
2214 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
2215     case acm2::ACMCodecDB::kISAC:
2216       *codec_name = "ISAC";
2217       *sample_rate_hz = 16000;
2218       *channels = 1;
2219       break;
2220 #endif
2221 #ifdef WEBRTC_CODEC_ISAC
2222     case acm2::ACMCodecDB::kISACSWB:
2223       *codec_name = "ISAC";
2224       *sample_rate_hz = 32000;
2225       *channels = 1;
2226       break;
2227     case acm2::ACMCodecDB::kISACFB:
2228       *codec_name = "ISAC";
2229       *sample_rate_hz = 48000;
2230       *channels = 1;
2231       break;
2232 #endif
2233 #ifdef WEBRTC_CODEC_ILBC
2234     case acm2::ACMCodecDB::kILBC:
2235       *codec_name = "ILBC";
2236       *sample_rate_hz = 8000;
2237       *channels = 1;
2238       break;
2239 #endif
2240     case acm2::ACMCodecDB::kPCMA:
2241       *codec_name = "PCMA";
2242       *sample_rate_hz = 8000;
2243       *channels = 1;
2244       break;
2245     case acm2::ACMCodecDB::kPCMA_2ch:
2246       *codec_name = "PCMA";
2247       *sample_rate_hz = 8000;
2248       *channels = 2;
2249       break;
2250     case acm2::ACMCodecDB::kPCMU:
2251       *codec_name = "PCMU";
2252       *sample_rate_hz = 8000;
2253       *channels = 1;
2254       break;
2255     case acm2::ACMCodecDB::kPCMU_2ch:
2256       *codec_name = "PCMU";
2257       *sample_rate_hz = 8000;
2258       *channels = 2;
2259       break;
2260 #ifdef WEBRTC_CODEC_G722
2261     case acm2::ACMCodecDB::kG722:
2262       *codec_name = "G722";
2263       *sample_rate_hz = 16000;
2264       *channels = 1;
2265       break;
2266     case acm2::ACMCodecDB::kG722_2ch:
2267       *codec_name = "G722";
2268       *sample_rate_hz = 16000;
2269       *channels = 2;
2270       break;
2271 #endif
2272 #ifdef WEBRTC_CODEC_OPUS
2273     case acm2::ACMCodecDB::kOpus:
2274       *codec_name = "opus";
2275       *sample_rate_hz = 48000;
2276       *channels = 2;
2277       break;
2278 #endif
2279     case acm2::ACMCodecDB::kCNNB:
2280       *codec_name = "CN";
2281       *sample_rate_hz = 8000;
2282       *channels = 1;
2283       break;
2284     case acm2::ACMCodecDB::kCNWB:
2285       *codec_name = "CN";
2286       *sample_rate_hz = 16000;
2287       *channels = 1;
2288       break;
2289     case acm2::ACMCodecDB::kCNSWB:
2290       *codec_name = "CN";
2291       *sample_rate_hz = 32000;
2292       *channels = 1;
2293       break;
2294     case acm2::ACMCodecDB::kRED:
2295       *codec_name = "red";
2296       *sample_rate_hz = 8000;
2297       *channels = 1;
2298       break;
2299 #ifdef WEBRTC_CODEC_AVT
2300     case acm2::ACMCodecDB::kAVT:
2301       *codec_name = "telephone-event";
2302       *sample_rate_hz = 8000;
2303       *channels = 1;
2304       break;
2305 #endif
2306     default:
2307       FATAL() << "Codec type " << codec_type << " not supported.";
2308   }
2309   return true;
2310 }
2311 
2312 }  // namespace webrtc
2313