• 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/acm_generic_codec.h"
12 
13 #include <assert.h>
14 #include <string.h>
15 
16 #include "webrtc/common_audio/vad/include/webrtc_vad.h"
17 #include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h"
18 #include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
19 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
20 #include "webrtc/system_wrappers/interface/trace.h"
21 
22 namespace webrtc {
23 
24 namespace acm2 {
25 
26 // Enum for CNG
27 enum {
28   kMaxPLCParamsCNG = WEBRTC_CNG_MAX_LPC_ORDER,
29   kNewCNGNumLPCParams = 8
30 };
31 
32 // Interval for sending new CNG parameters (SID frames) is 100 msec.
33 enum {
34   kCngSidIntervalMsec = 100
35 };
36 
37 // We set some of the variables to invalid values as a check point
38 // if a proper initialization has happened. Another approach is
39 // to initialize to a default codec that we are sure is always included.
ACMGenericCodec()40 ACMGenericCodec::ACMGenericCodec()
41     : in_audio_ix_write_(0),
42       in_audio_ix_read_(0),
43       in_timestamp_ix_write_(0),
44       in_audio_(NULL),
45       in_timestamp_(NULL),
46       frame_len_smpl_(-1),  // invalid value
47       num_channels_(1),
48       codec_id_(-1),  // invalid value
49       num_missed_samples_(0),
50       encoder_exist_(false),
51       encoder_initialized_(false),
52       registered_in_neteq_(false),
53       has_internal_dtx_(false),
54       ptr_vad_inst_(NULL),
55       vad_enabled_(false),
56       vad_mode_(VADNormal),
57       dtx_enabled_(false),
58       ptr_dtx_inst_(NULL),
59       num_lpc_params_(kNewCNGNumLPCParams),
60       sent_cn_previous_(false),
61       prev_frame_cng_(0),
62       has_internal_fec_(false),
63       neteq_decode_lock_(NULL),
64       codec_wrapper_lock_(*RWLockWrapper::CreateRWLock()),
65       last_timestamp_(0xD87F3F9F),
66       unique_id_(0) {
67   // Initialize VAD vector.
68   for (int i = 0; i < MAX_FRAME_SIZE_10MSEC; i++) {
69     vad_label_[i] = 0;
70   }
71   // Nullify memory for encoder and decoder, and set payload type to an
72   // invalid value.
73   memset(&encoder_params_, 0, sizeof(WebRtcACMCodecParams));
74   encoder_params_.codec_inst.pltype = -1;
75 }
76 
~ACMGenericCodec()77 ACMGenericCodec::~ACMGenericCodec() {
78   // Check all the members which are pointers, and if they are not NULL
79   // delete/free them.
80   if (ptr_vad_inst_ != NULL) {
81     WebRtcVad_Free(ptr_vad_inst_);
82     ptr_vad_inst_ = NULL;
83   }
84   if (in_audio_ != NULL) {
85     delete[] in_audio_;
86     in_audio_ = NULL;
87   }
88   if (in_timestamp_ != NULL) {
89     delete[] in_timestamp_;
90     in_timestamp_ = NULL;
91   }
92   if (ptr_dtx_inst_ != NULL) {
93     WebRtcCng_FreeEnc(ptr_dtx_inst_);
94     ptr_dtx_inst_ = NULL;
95   }
96   delete &codec_wrapper_lock_;
97 }
98 
Add10MsData(const uint32_t timestamp,const int16_t * data,const uint16_t length_smpl,const uint8_t audio_channel)99 int32_t ACMGenericCodec::Add10MsData(const uint32_t timestamp,
100                                      const int16_t* data,
101                                      const uint16_t length_smpl,
102                                      const uint8_t audio_channel) {
103   WriteLockScoped wl(codec_wrapper_lock_);
104   return Add10MsDataSafe(timestamp, data, length_smpl, audio_channel);
105 }
106 
Add10MsDataSafe(const uint32_t timestamp,const int16_t * data,const uint16_t length_smpl,const uint8_t audio_channel)107 int32_t ACMGenericCodec::Add10MsDataSafe(const uint32_t timestamp,
108                                          const int16_t* data,
109                                          const uint16_t length_smpl,
110                                          const uint8_t audio_channel) {
111   // The codec expects to get data in correct sampling rate. Get the sampling
112   // frequency of the codec.
113   uint16_t plfreq_hz;
114   if (EncoderSampFreq(&plfreq_hz) < 0) {
115     return -1;
116   }
117 
118   // Sanity check to make sure the length of the input corresponds to 10 ms.
119   if ((plfreq_hz / 100) != length_smpl) {
120     // This is not 10 ms of audio, given the sampling frequency of the codec.
121     return -1;
122   }
123 
124   if (last_timestamp_ == timestamp) {
125     // Same timestamp as the last time, overwrite.
126     if ((in_audio_ix_write_ >= length_smpl * audio_channel) &&
127         (in_timestamp_ix_write_ > 0)) {
128       in_audio_ix_write_ -= length_smpl * audio_channel;
129       assert(in_timestamp_ix_write_ >= 0);
130 
131       in_timestamp_ix_write_--;
132       assert(in_audio_ix_write_ >= 0);
133       WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_,
134                    "Adding 10ms with previous timestamp, overwriting the "
135                    "previous 10ms");
136     } else {
137       WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_,
138                    "Adding 10ms with previous timestamp, this will sound bad");
139     }
140   }
141 
142   last_timestamp_ = timestamp;
143 
144   // If the data exceeds the buffer size, we throw away the oldest data and
145   // add the newly received 10 msec at the end.
146   if ((in_audio_ix_write_ + length_smpl * audio_channel) >
147       AUDIO_BUFFER_SIZE_W16) {
148     // Get the number of samples to be overwritten.
149     int16_t missed_samples = in_audio_ix_write_ + length_smpl * audio_channel -
150         AUDIO_BUFFER_SIZE_W16;
151 
152     // Move the data (overwrite the old data).
153     memmove(in_audio_, in_audio_ + missed_samples,
154             (AUDIO_BUFFER_SIZE_W16 - length_smpl * audio_channel) *
155             sizeof(int16_t));
156 
157     // Copy the new data.
158     memcpy(in_audio_ + (AUDIO_BUFFER_SIZE_W16 - length_smpl * audio_channel),
159            data, length_smpl * audio_channel * sizeof(int16_t));
160 
161     // Get the number of 10 ms blocks which are overwritten.
162     int16_t missed_10ms_blocks =static_cast<int16_t>(
163         (missed_samples / audio_channel * 100) / plfreq_hz);
164 
165     // Move the timestamps.
166     memmove(in_timestamp_, in_timestamp_ + missed_10ms_blocks,
167             (in_timestamp_ix_write_ - missed_10ms_blocks) * sizeof(uint32_t));
168     in_timestamp_ix_write_ -= missed_10ms_blocks;
169     assert(in_timestamp_ix_write_ >= 0);
170 
171     in_timestamp_[in_timestamp_ix_write_] = timestamp;
172     in_timestamp_ix_write_++;
173     assert(in_timestamp_ix_write_ < TIMESTAMP_BUFFER_SIZE_W32);
174 
175     // Buffer is full.
176     in_audio_ix_write_ = AUDIO_BUFFER_SIZE_W16;
177     IncreaseNoMissedSamples(missed_samples);
178     return -missed_samples;
179   }
180 
181   // Store the input data in our data buffer.
182   memcpy(in_audio_ + in_audio_ix_write_, data,
183          length_smpl * audio_channel * sizeof(int16_t));
184   in_audio_ix_write_ += length_smpl * audio_channel;
185   assert(in_timestamp_ix_write_ < TIMESTAMP_BUFFER_SIZE_W32);
186 
187   in_timestamp_[in_timestamp_ix_write_] = timestamp;
188   in_timestamp_ix_write_++;
189   assert(in_timestamp_ix_write_ < TIMESTAMP_BUFFER_SIZE_W32);
190   return 0;
191 }
192 
HasFrameToEncode() const193 bool ACMGenericCodec::HasFrameToEncode() const {
194   ReadLockScoped lockCodec(codec_wrapper_lock_);
195   if (in_audio_ix_write_ < frame_len_smpl_ * num_channels_)
196     return false;
197   return true;
198 }
199 
Encode(uint8_t * bitstream,int16_t * bitstream_len_byte,uint32_t * timestamp,WebRtcACMEncodingType * encoding_type)200 int16_t ACMGenericCodec::Encode(uint8_t* bitstream,
201                                 int16_t* bitstream_len_byte,
202                                 uint32_t* timestamp,
203                                 WebRtcACMEncodingType* encoding_type) {
204   if (!HasFrameToEncode()) {
205     // There is not enough audio
206     *timestamp = 0;
207     *bitstream_len_byte = 0;
208     // Doesn't really matter what this parameter set to
209     *encoding_type = kNoEncoding;
210     return 0;
211   }
212   WriteLockScoped lockCodec(codec_wrapper_lock_);
213   ReadLockScoped lockNetEq(*neteq_decode_lock_);
214 
215   // Not all codecs accept the whole frame to be pushed into encoder at once.
216   // Some codecs needs to be feed with a specific number of samples different
217   // from the frame size. If this is the case, |myBasicCodingBlockSmpl| will
218   // report a number different from 0, and we will loop over calls to encoder
219   // further down, until we have encode a complete frame.
220   const int16_t my_basic_coding_block_smpl =
221       ACMCodecDB::BasicCodingBlock(codec_id_);
222   if (my_basic_coding_block_smpl < 0 || !encoder_initialized_ ||
223       !encoder_exist_) {
224     // This should not happen, but in case it does, report no encoding done.
225     *timestamp = 0;
226     *bitstream_len_byte = 0;
227     *encoding_type = kNoEncoding;
228     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
229                  "EncodeSafe: error, basic coding sample block is negative");
230     return -1;
231   }
232   // This makes the internal encoder read from the beginning of the buffer.
233   in_audio_ix_read_ = 0;
234   *timestamp = in_timestamp_[0];
235 
236   // Process the audio through VAD. The function will set |_vad_labels|.
237   // If VAD is disabled all entries in |_vad_labels| are set to ONE (active).
238   int16_t status = 0;
239   int16_t dtx_processed_samples = 0;
240   status = ProcessFrameVADDTX(bitstream, bitstream_len_byte,
241                               &dtx_processed_samples);
242   if (status < 0) {
243     *timestamp = 0;
244     *bitstream_len_byte = 0;
245     *encoding_type = kNoEncoding;
246   } else {
247     if (dtx_processed_samples > 0) {
248       // Dtx have processed some samples, and even if a bit-stream is generated
249       // we should not do any encoding (normally there won't be enough data).
250 
251       // Setting the following makes sure that the move of audio data and
252       // timestamps done correctly.
253       in_audio_ix_read_ = dtx_processed_samples;
254       // This will let the owner of ACMGenericCodec to know that the
255       // generated bit-stream is DTX to use correct payload type.
256       uint16_t samp_freq_hz;
257       EncoderSampFreq(&samp_freq_hz);
258       if (samp_freq_hz == 8000) {
259         *encoding_type = kPassiveDTXNB;
260       } else if (samp_freq_hz == 16000) {
261         *encoding_type = kPassiveDTXWB;
262       } else if (samp_freq_hz == 32000) {
263         *encoding_type = kPassiveDTXSWB;
264       } else if (samp_freq_hz == 48000) {
265         *encoding_type = kPassiveDTXFB;
266       } else {
267         status = -1;
268         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
269                      "EncodeSafe: Wrong sampling frequency for DTX.");
270       }
271 
272       // Transport empty frame if we have an empty bitstream.
273       if ((*bitstream_len_byte == 0) &&
274           (sent_cn_previous_ ||
275           ((in_audio_ix_write_ - in_audio_ix_read_) <= 0))) {
276         // Makes sure we transmit an empty frame.
277         *bitstream_len_byte = 1;
278         *encoding_type = kNoEncoding;
279       }
280       sent_cn_previous_ = true;
281     } else {
282       // We should encode the audio frame. Either VAD and/or DTX is off, or the
283       // audio was considered "active".
284 
285       sent_cn_previous_ = false;
286       if (my_basic_coding_block_smpl == 0) {
287         // This codec can handle all allowed frame sizes as basic coding block.
288         status = InternalEncode(bitstream, bitstream_len_byte);
289         if (status < 0) {
290           // TODO(tlegrand): Maybe reseting the encoder to be fresh for the next
291           // frame.
292           WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding,
293                        unique_id_, "EncodeSafe: error in internal_encode");
294           *bitstream_len_byte = 0;
295           *encoding_type = kNoEncoding;
296         }
297       } else {
298         // A basic-coding-block for this codec is defined so we loop over the
299         // audio with the steps of the basic-coding-block.
300         int16_t tmp_bitstream_len_byte;
301 
302         // Reset the variables which will be incremented in the loop.
303         *bitstream_len_byte = 0;
304         bool done = false;
305         while (!done) {
306           status = InternalEncode(&bitstream[*bitstream_len_byte],
307                                   &tmp_bitstream_len_byte);
308           *bitstream_len_byte += tmp_bitstream_len_byte;
309 
310           // Guard Against errors and too large payloads.
311           if ((status < 0) || (*bitstream_len_byte > MAX_PAYLOAD_SIZE_BYTE)) {
312             // Error has happened, and even if we are in the middle of a full
313             // frame we have to exit. Before exiting, whatever bits are in the
314             // buffer are probably corrupted, so we ignore them.
315             *bitstream_len_byte = 0;
316             *encoding_type = kNoEncoding;
317             // We might have come here because of the second condition.
318             status = -1;
319             WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding,
320                          unique_id_, "EncodeSafe: error in InternalEncode");
321             // break from the loop
322             break;
323           }
324           done = in_audio_ix_read_ >= frame_len_smpl_ * num_channels_;
325         }
326       }
327       if (status >= 0) {
328         *encoding_type = (vad_label_[0] == 1) ? kActiveNormalEncoded :
329             kPassiveNormalEncoded;
330         // Transport empty frame if we have an empty bitstream.
331         if ((*bitstream_len_byte == 0) &&
332             ((in_audio_ix_write_ - in_audio_ix_read_) <= 0)) {
333           // Makes sure we transmit an empty frame.
334           *bitstream_len_byte = 1;
335           *encoding_type = kNoEncoding;
336         }
337       }
338     }
339   }
340 
341   // Move the timestamp buffer according to the number of 10 ms blocks
342   // which are read.
343   uint16_t samp_freq_hz;
344   EncoderSampFreq(&samp_freq_hz);
345   int16_t num_10ms_blocks = static_cast<int16_t>(
346       (in_audio_ix_read_ / num_channels_ * 100) / samp_freq_hz);
347   if (in_timestamp_ix_write_ > num_10ms_blocks) {
348     memmove(in_timestamp_, in_timestamp_ + num_10ms_blocks,
349             (in_timestamp_ix_write_ - num_10ms_blocks) * sizeof(int32_t));
350   }
351   in_timestamp_ix_write_ -= num_10ms_blocks;
352   assert(in_timestamp_ix_write_ >= 0);
353 
354   // Remove encoded audio and move next audio to be encoded to the beginning
355   // of the buffer. Accordingly, adjust the read and write indices.
356   if (in_audio_ix_read_ < in_audio_ix_write_) {
357     memmove(in_audio_, &in_audio_[in_audio_ix_read_],
358             (in_audio_ix_write_ - in_audio_ix_read_) * sizeof(int16_t));
359   }
360   in_audio_ix_write_ -= in_audio_ix_read_;
361   in_audio_ix_read_ = 0;
362   return (status < 0) ? (-1) : (*bitstream_len_byte);
363 }
364 
EncoderInitialized()365 bool ACMGenericCodec::EncoderInitialized() {
366   ReadLockScoped rl(codec_wrapper_lock_);
367   return encoder_initialized_;
368 }
369 
EncoderParams(WebRtcACMCodecParams * enc_params)370 int16_t ACMGenericCodec::EncoderParams(WebRtcACMCodecParams* enc_params) {
371   ReadLockScoped rl(codec_wrapper_lock_);
372   return EncoderParamsSafe(enc_params);
373 }
374 
EncoderParamsSafe(WebRtcACMCodecParams * enc_params)375 int16_t ACMGenericCodec::EncoderParamsSafe(WebRtcACMCodecParams* enc_params) {
376   // Codec parameters are valid only if the encoder is initialized.
377   if (encoder_initialized_) {
378     int32_t current_rate;
379     memcpy(enc_params, &encoder_params_, sizeof(WebRtcACMCodecParams));
380     current_rate = enc_params->codec_inst.rate;
381     CurrentRate(&current_rate);
382     enc_params->codec_inst.rate = current_rate;
383     return 0;
384   } else {
385     enc_params->codec_inst.plname[0] = '\0';
386     enc_params->codec_inst.pltype = -1;
387     enc_params->codec_inst.pacsize = 0;
388     enc_params->codec_inst.rate = 0;
389     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
390                  "EncoderParamsSafe: error, encoder not initialized");
391     return -1;
392   }
393 }
394 
ResetEncoder()395 int16_t ACMGenericCodec::ResetEncoder() {
396   WriteLockScoped lockCodec(codec_wrapper_lock_);
397   ReadLockScoped lockNetEq(*neteq_decode_lock_);
398   return ResetEncoderSafe();
399 }
400 
ResetEncoderSafe()401 int16_t ACMGenericCodec::ResetEncoderSafe() {
402   if (!encoder_exist_ || !encoder_initialized_) {
403     // We don't reset if encoder doesn't exists or isn't initialized yet.
404     return 0;
405   }
406 
407   in_audio_ix_write_ = 0;
408   in_audio_ix_read_ = 0;
409   in_timestamp_ix_write_ = 0;
410   num_missed_samples_ = 0;
411   memset(in_audio_, 0, AUDIO_BUFFER_SIZE_W16 * sizeof(int16_t));
412   memset(in_timestamp_, 0, TIMESTAMP_BUFFER_SIZE_W32 * sizeof(int32_t));
413 
414   // Store DTX/VAD parameters.
415   bool enable_vad = vad_enabled_;
416   bool enable_dtx = dtx_enabled_;
417   ACMVADMode mode = vad_mode_;
418 
419   // Reset the encoder.
420   if (InternalResetEncoder() < 0) {
421     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
422                  "ResetEncoderSafe: error in reset encoder");
423     return -1;
424   }
425 
426   // Disable DTX & VAD to delete the states and have a fresh start.
427   DisableDTX();
428   DisableVAD();
429 
430   // Set DTX/VAD.
431   int status = SetVADSafe(&enable_dtx, &enable_vad, &mode);
432   dtx_enabled_ = enable_dtx;
433   vad_enabled_ = enable_vad;
434   vad_mode_ = mode;
435   return status;
436 }
437 
InternalResetEncoder()438 int16_t ACMGenericCodec::InternalResetEncoder() {
439   // Call the codecs internal encoder initialization/reset function.
440   return InternalInitEncoder(&encoder_params_);
441 }
442 
InitEncoder(WebRtcACMCodecParams * codec_params,bool force_initialization)443 int16_t ACMGenericCodec::InitEncoder(WebRtcACMCodecParams* codec_params,
444                                      bool force_initialization) {
445   WriteLockScoped lockCodec(codec_wrapper_lock_);
446   ReadLockScoped lockNetEq(*neteq_decode_lock_);
447   return InitEncoderSafe(codec_params, force_initialization);
448 }
449 
InitEncoderSafe(WebRtcACMCodecParams * codec_params,bool force_initialization)450 int16_t ACMGenericCodec::InitEncoderSafe(WebRtcACMCodecParams* codec_params,
451                                          bool force_initialization) {
452   // Check if we got a valid set of parameters.
453   int mirrorID;
454   int codec_number = ACMCodecDB::CodecNumber(codec_params->codec_inst,
455                                              &mirrorID);
456   assert(codec_number >= 0);
457 
458   // Check if the parameters are for this codec.
459   if ((codec_id_ >= 0) && (codec_id_ != codec_number) &&
460       (codec_id_ != mirrorID)) {
461     // The current codec is not the same as the one given by codec_params.
462     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
463                  "InitEncoderSafe: current codec is not the same as the one "
464                  "given by codec_params");
465     return -1;
466   }
467 
468   if (encoder_initialized_ && !force_initialization) {
469     // The encoder is already initialized, and we don't want to force
470     // initialization.
471     return 0;
472   }
473   int16_t status;
474   if (!encoder_exist_) {
475     // New encoder, start with creating.
476     encoder_initialized_ = false;
477     status = CreateEncoder();
478     if (status < 0) {
479       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
480                    "InitEncoderSafe: cannot create encoder");
481       return -1;
482     } else {
483       encoder_exist_ = true;
484     }
485   }
486   frame_len_smpl_ = codec_params->codec_inst.pacsize;
487   num_channels_ = codec_params->codec_inst.channels;
488   status = InternalInitEncoder(codec_params);
489   if (status < 0) {
490     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
491                  "InitEncoderSafe: error in init encoder");
492     encoder_initialized_ = false;
493     return -1;
494   } else {
495     // TODO(turajs): Move these allocations to the constructor issue 2445.
496     // Store encoder parameters.
497     memcpy(&encoder_params_, codec_params, sizeof(WebRtcACMCodecParams));
498     encoder_initialized_ = true;
499     if (in_audio_ == NULL) {
500       in_audio_ = new int16_t[AUDIO_BUFFER_SIZE_W16];
501     }
502     if (in_timestamp_ == NULL) {
503       in_timestamp_ = new uint32_t[TIMESTAMP_BUFFER_SIZE_W32];
504     }
505   }
506 
507   // Fresh start of audio buffer.
508   memset(in_audio_, 0, sizeof(*in_audio_) * AUDIO_BUFFER_SIZE_W16);
509   memset(in_timestamp_, 0, sizeof(*in_timestamp_) * TIMESTAMP_BUFFER_SIZE_W32);
510   in_audio_ix_write_ = 0;
511   in_audio_ix_read_ = 0;
512   in_timestamp_ix_write_ = 0;
513 
514   return SetVADSafe(&codec_params->enable_dtx, &codec_params->enable_vad,
515                     &codec_params->vad_mode);
516 }
517 
ResetNoMissedSamples()518 void ACMGenericCodec::ResetNoMissedSamples() {
519   WriteLockScoped cs(codec_wrapper_lock_);
520   num_missed_samples_ = 0;
521 }
522 
IncreaseNoMissedSamples(const int16_t num_samples)523 void ACMGenericCodec::IncreaseNoMissedSamples(const int16_t num_samples) {
524   num_missed_samples_ += num_samples;
525 }
526 
527 // Get the number of missed samples, this can be public.
NoMissedSamples() const528 uint32_t ACMGenericCodec::NoMissedSamples() const {
529   ReadLockScoped cs(codec_wrapper_lock_);
530   return num_missed_samples_;
531 }
532 
DestructEncoder()533 void ACMGenericCodec::DestructEncoder() {
534   WriteLockScoped wl(codec_wrapper_lock_);
535 
536   // Disable VAD and delete the instance.
537   if (ptr_vad_inst_ != NULL) {
538     WebRtcVad_Free(ptr_vad_inst_);
539     ptr_vad_inst_ = NULL;
540   }
541   vad_enabled_ = false;
542   vad_mode_ = VADNormal;
543 
544   // Disable DTX and delete the instance.
545   dtx_enabled_ = false;
546   if (ptr_dtx_inst_ != NULL) {
547     WebRtcCng_FreeEnc(ptr_dtx_inst_);
548     ptr_dtx_inst_ = NULL;
549   }
550   num_lpc_params_ = kNewCNGNumLPCParams;
551 
552   DestructEncoderSafe();
553 }
554 
SetBitRate(const int32_t bitrate_bps)555 int16_t ACMGenericCodec::SetBitRate(const int32_t bitrate_bps) {
556   WriteLockScoped wl(codec_wrapper_lock_);
557   return SetBitRateSafe(bitrate_bps);
558 }
559 
SetBitRateSafe(const int32_t bitrate_bps)560 int16_t ACMGenericCodec::SetBitRateSafe(const int32_t bitrate_bps) {
561   // If the codec can change the bit-rate this function is overloaded.
562   // Otherwise the only acceptable value is the one that is in the database.
563   CodecInst codec_params;
564   if (ACMCodecDB::Codec(codec_id_, &codec_params) < 0) {
565     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
566                  "SetBitRateSafe: error in ACMCodecDB::Codec");
567     return -1;
568   }
569   if (codec_params.rate != bitrate_bps) {
570     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
571                  "SetBitRateSafe: rate value is not acceptable");
572     return -1;
573   } else {
574     return 0;
575   }
576 }
577 
578 // iSAC specific functions:
GetEstimatedBandwidth()579 int32_t ACMGenericCodec::GetEstimatedBandwidth() {
580   WriteLockScoped wl(codec_wrapper_lock_);
581   return GetEstimatedBandwidthSafe();
582 }
583 
GetEstimatedBandwidthSafe()584 int32_t ACMGenericCodec::GetEstimatedBandwidthSafe() {
585   // All codecs but iSAC will return -1.
586   return -1;
587 }
588 
SetEstimatedBandwidth(int32_t estimated_bandwidth)589 int32_t ACMGenericCodec::SetEstimatedBandwidth(int32_t estimated_bandwidth) {
590   WriteLockScoped wl(codec_wrapper_lock_);
591   return SetEstimatedBandwidthSafe(estimated_bandwidth);
592 }
593 
SetEstimatedBandwidthSafe(int32_t)594 int32_t ACMGenericCodec::SetEstimatedBandwidthSafe(
595     int32_t /*estimated_bandwidth*/) {
596   // All codecs but iSAC will return -1.
597   return -1;
598 }
599 // End of iSAC specific functions.
600 
GetRedPayload(uint8_t * red_payload,int16_t * payload_bytes)601 int32_t ACMGenericCodec::GetRedPayload(uint8_t* red_payload,
602                                        int16_t* payload_bytes) {
603   WriteLockScoped wl(codec_wrapper_lock_);
604   return GetRedPayloadSafe(red_payload, payload_bytes);
605 }
606 
GetRedPayloadSafe(uint8_t *,int16_t *)607 int32_t ACMGenericCodec::GetRedPayloadSafe(uint8_t* /* red_payload */,
608                                            int16_t* /* payload_bytes */) {
609   return -1;  // Do nothing by default.
610 }
611 
CreateEncoder()612 int16_t ACMGenericCodec::CreateEncoder() {
613   int16_t status = 0;
614   if (!encoder_exist_) {
615     status = InternalCreateEncoder();
616     // We just created the codec and obviously it is not initialized.
617     encoder_initialized_ = false;
618   }
619   if (status < 0) {
620     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
621                  "CreateEncoder: error in internal create encoder");
622     encoder_exist_ = false;
623   } else {
624     encoder_exist_ = true;
625   }
626   return status;
627 }
628 
DestructEncoderInst(void * ptr_inst)629 void ACMGenericCodec::DestructEncoderInst(void* ptr_inst) {
630   if (ptr_inst != NULL) {
631     WriteLockScoped lockCodec(codec_wrapper_lock_);
632     ReadLockScoped lockNetEq(*neteq_decode_lock_);
633     InternalDestructEncoderInst(ptr_inst);
634   }
635 }
636 
EarliestTimestamp() const637 uint32_t ACMGenericCodec::EarliestTimestamp() const {
638   ReadLockScoped cs(codec_wrapper_lock_);
639   return in_timestamp_[0];
640 }
641 
SetVAD(bool * enable_dtx,bool * enable_vad,ACMVADMode * mode)642 int16_t ACMGenericCodec::SetVAD(bool* enable_dtx,
643                                 bool* enable_vad,
644                                 ACMVADMode* mode) {
645   WriteLockScoped cs(codec_wrapper_lock_);
646   return SetVADSafe(enable_dtx, enable_vad, mode);
647 }
648 
SetVADSafe(bool * enable_dtx,bool * enable_vad,ACMVADMode * mode)649 int16_t ACMGenericCodec::SetVADSafe(bool* enable_dtx,
650                                     bool* enable_vad,
651                                     ACMVADMode* mode) {
652   if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "OPUS") ||
653       encoder_params_.codec_inst.channels == 2 ) {
654     // VAD/DTX is not supported for Opus (even if sending mono), or other
655     // stereo codecs.
656     DisableDTX();
657     DisableVAD();
658     *enable_dtx = false;
659     *enable_vad = false;
660     return 0;
661   }
662 
663   if (*enable_dtx) {
664     // Make G729 AnnexB a special case.
665     if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "G729")
666         && !has_internal_dtx_) {
667       if (ACMGenericCodec::EnableDTX() < 0) {
668         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
669                      "SetVADSafe: error in enable DTX");
670         *enable_dtx = false;
671         *enable_vad = vad_enabled_;
672         return -1;
673       }
674     } else {
675       if (EnableDTX() < 0) {
676         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
677                      "SetVADSafe: error in enable DTX");
678         *enable_dtx = false;
679         *enable_vad = vad_enabled_;
680         return -1;
681       }
682     }
683 
684     // If codec does not have internal DTX (normal case) enabling DTX requires
685     // an active VAD. '*enable_dtx == true' overwrites VAD status.
686     // If codec has internal DTX, practically we don't need WebRtc VAD, however,
687     // we let the user to turn it on if they need call-backs on silence.
688     if (!has_internal_dtx_) {
689       // DTX is enabled, and VAD will be activated.
690       *enable_vad = true;
691     }
692   } else {
693     // Make G729 AnnexB a special case.
694     if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "G729")
695         && !has_internal_dtx_) {
696       ACMGenericCodec::DisableDTX();
697       *enable_dtx = false;
698     } else {
699       DisableDTX();
700       *enable_dtx = false;
701     }
702   }
703 
704   int16_t status = (*enable_vad) ? EnableVAD(*mode) : DisableVAD();
705   if (status < 0) {
706     // Failed to set VAD, disable DTX.
707     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
708     "SetVADSafe: error in enable VAD");
709     DisableDTX();
710     *enable_dtx = false;
711     *enable_vad = false;
712   }
713   return status;
714 }
715 
EnableDTX()716 int16_t ACMGenericCodec::EnableDTX() {
717   if (has_internal_dtx_) {
718     // We should not be here if we have internal DTX this function should be
719     // overloaded by the derived class in this case.
720     return -1;
721   }
722   if (!dtx_enabled_) {
723     if (WebRtcCng_CreateEnc(&ptr_dtx_inst_) < 0) {
724       ptr_dtx_inst_ = NULL;
725       return -1;
726     }
727     uint16_t freq_hz;
728     EncoderSampFreq(&freq_hz);
729     if (WebRtcCng_InitEnc(ptr_dtx_inst_, freq_hz, kCngSidIntervalMsec,
730                           num_lpc_params_) < 0) {
731       // Couldn't initialize, has to return -1, and free the memory.
732       WebRtcCng_FreeEnc(ptr_dtx_inst_);
733       ptr_dtx_inst_ = NULL;
734       return -1;
735     }
736     dtx_enabled_ = true;
737   }
738   return 0;
739 }
740 
DisableDTX()741 int16_t ACMGenericCodec::DisableDTX() {
742   if (has_internal_dtx_) {
743     // We should not be here if we have internal DTX this function should be
744     // overloaded by the derived class in this case.
745     return -1;
746   }
747   if (ptr_dtx_inst_ != NULL) {
748     WebRtcCng_FreeEnc(ptr_dtx_inst_);
749     ptr_dtx_inst_ = NULL;
750   }
751   dtx_enabled_ = false;
752   return 0;
753 }
754 
EnableVAD(ACMVADMode mode)755 int16_t ACMGenericCodec::EnableVAD(ACMVADMode mode) {
756   if ((mode < VADNormal) || (mode > VADVeryAggr)) {
757     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
758                  "EnableVAD: error in VAD mode range");
759     return -1;
760   }
761 
762   if (!vad_enabled_) {
763     if (WebRtcVad_Create(&ptr_vad_inst_) < 0) {
764       ptr_vad_inst_ = NULL;
765       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
766                    "EnableVAD: error in create VAD");
767       return -1;
768     }
769     if (WebRtcVad_Init(ptr_vad_inst_) < 0) {
770       WebRtcVad_Free(ptr_vad_inst_);
771       ptr_vad_inst_ = NULL;
772       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
773                    "EnableVAD: error in init VAD");
774       return -1;
775     }
776   }
777 
778   // Set the VAD mode to the given value.
779   if (WebRtcVad_set_mode(ptr_vad_inst_, mode) < 0) {
780     // We failed to set the mode and we have to return -1. If we already have a
781     // working VAD (vad_enabled_ == true) then we leave it to work. Otherwise,
782     // the following will be executed.
783     if (!vad_enabled_) {
784       // We just created the instance but cannot set the mode we have to free
785       // the memory.
786       WebRtcVad_Free(ptr_vad_inst_);
787       ptr_vad_inst_ = NULL;
788     }
789     WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_,
790                  "EnableVAD: failed to set the VAD mode");
791     return -1;
792   }
793   vad_mode_ = mode;
794   vad_enabled_ = true;
795   return 0;
796 }
797 
DisableVAD()798 int16_t ACMGenericCodec::DisableVAD() {
799   if (ptr_vad_inst_ != NULL) {
800     WebRtcVad_Free(ptr_vad_inst_);
801     ptr_vad_inst_ = NULL;
802   }
803   vad_enabled_ = false;
804   return 0;
805 }
806 
ReplaceInternalDTX(const bool replace_internal_dtx)807 int32_t ACMGenericCodec::ReplaceInternalDTX(const bool replace_internal_dtx) {
808   WriteLockScoped cs(codec_wrapper_lock_);
809   return ReplaceInternalDTXSafe(replace_internal_dtx);
810 }
811 
ReplaceInternalDTXSafe(const bool)812 int32_t ACMGenericCodec::ReplaceInternalDTXSafe(
813     const bool /* replace_internal_dtx */) {
814   return -1;
815 }
816 
IsInternalDTXReplaced(bool * internal_dtx_replaced)817 int32_t ACMGenericCodec::IsInternalDTXReplaced(bool* internal_dtx_replaced) {
818   WriteLockScoped cs(codec_wrapper_lock_);
819   return IsInternalDTXReplacedSafe(internal_dtx_replaced);
820 }
821 
IsInternalDTXReplacedSafe(bool * internal_dtx_replaced)822 int32_t ACMGenericCodec::IsInternalDTXReplacedSafe(
823     bool* internal_dtx_replaced) {
824   *internal_dtx_replaced = false;
825   return 0;
826 }
827 
ProcessFrameVADDTX(uint8_t * bitstream,int16_t * bitstream_len_byte,int16_t * samples_processed)828 int16_t ACMGenericCodec::ProcessFrameVADDTX(uint8_t* bitstream,
829                                             int16_t* bitstream_len_byte,
830                                             int16_t* samples_processed) {
831   if (!vad_enabled_) {
832     // VAD not enabled, set all |vad_lable_[]| to 1 (speech detected).
833     for (int n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
834       vad_label_[n] = 1;
835     }
836     *samples_processed = 0;
837     return 0;
838   }
839 
840   uint16_t freq_hz;
841   EncoderSampFreq(&freq_hz);
842 
843   // Calculate number of samples in 10 ms blocks, and number ms in one frame.
844   int16_t samples_in_10ms = static_cast<int16_t>(freq_hz / 100);
845   int32_t frame_len_ms = static_cast<int32_t>(frame_len_smpl_) * 1000 / freq_hz;
846   int16_t status;
847 
848   // Vector for storing maximum 30 ms of mono audio at 48 kHz.
849   int16_t audio[1440];
850 
851   // Calculate number of VAD-blocks to process, and number of samples in each
852   // block.
853   int num_samples_to_process[2];
854   if (frame_len_ms == 40) {
855     // 20 ms in each VAD block.
856     num_samples_to_process[0] = num_samples_to_process[1] = 2 * samples_in_10ms;
857   } else {
858     // For 10-30 ms framesizes, second VAD block will be size zero ms,
859     // for 50 and 60 ms first VAD block will be 30 ms.
860     num_samples_to_process[0] =
861         (frame_len_ms > 30) ? 3 * samples_in_10ms : frame_len_smpl_;
862     num_samples_to_process[1] = frame_len_smpl_ - num_samples_to_process[0];
863   }
864 
865   int offset = 0;
866   int loops = (num_samples_to_process[1] > 0) ? 2 : 1;
867   for (int i = 0; i < loops; i++) {
868     // TODO(turajs): Do we need to care about VAD together with stereo?
869     // If stereo, calculate mean of the two channels.
870     if (num_channels_ == 2) {
871       for (int j = 0; j < num_samples_to_process[i]; j++) {
872         audio[j] = (in_audio_[(offset + j) * 2] +
873             in_audio_[(offset + j) * 2 + 1]) / 2;
874       }
875       offset = num_samples_to_process[0];
876     } else {
877       // Mono, copy data from in_audio_ to continue work on.
878       memcpy(audio, in_audio_, sizeof(int16_t) * num_samples_to_process[i]);
879     }
880 
881     // Call VAD.
882     status = static_cast<int16_t>(WebRtcVad_Process(ptr_vad_inst_,
883                                                     static_cast<int>(freq_hz),
884                                                     audio,
885                                                     num_samples_to_process[i]));
886     vad_label_[i] = status;
887 
888     if (status < 0) {
889       // This will force that the data be removed from the buffer.
890       *samples_processed += num_samples_to_process[i];
891       return -1;
892     }
893 
894     // If VAD decision non-active, update DTX. NOTE! We only do this if the
895     // first part of a frame gets the VAD decision "inactive". Otherwise DTX
896     // might say it is time to transmit SID frame, but we will encode the whole
897     // frame, because the first part is active.
898     *samples_processed = 0;
899     if ((status == 0) && (i == 0) && dtx_enabled_ && !has_internal_dtx_) {
900       int16_t bitstream_len;
901       int num_10ms_frames = num_samples_to_process[i] / samples_in_10ms;
902       *bitstream_len_byte = 0;
903       for (int n = 0; n < num_10ms_frames; n++) {
904         // This block is (passive) && (vad enabled). If first CNG after
905         // speech, force SID by setting last parameter to "1".
906         status = WebRtcCng_Encode(ptr_dtx_inst_, &audio[n * samples_in_10ms],
907                                   samples_in_10ms, bitstream, &bitstream_len,
908                                   !prev_frame_cng_);
909         if (status < 0) {
910           return -1;
911         }
912 
913         // Update previous frame was CNG.
914         prev_frame_cng_ = 1;
915 
916         *samples_processed += samples_in_10ms * num_channels_;
917 
918         // |bitstream_len_byte| will only be > 0 once per 100 ms.
919         *bitstream_len_byte += bitstream_len;
920       }
921 
922       // Check if all samples got processed by the DTX.
923       if (*samples_processed != num_samples_to_process[i] * num_channels_) {
924         // Set to zero since something went wrong. Shouldn't happen.
925         *samples_processed = 0;
926       }
927     } else {
928       // Update previous frame was not CNG.
929       prev_frame_cng_ = 0;
930     }
931 
932     if (*samples_processed > 0) {
933       // The block contains inactive speech, and is processed by DTX.
934       // Discontinue running VAD.
935       break;
936     }
937   }
938 
939   return status;
940 }
941 
SamplesLeftToEncode()942 int16_t ACMGenericCodec::SamplesLeftToEncode() {
943   ReadLockScoped rl(codec_wrapper_lock_);
944   return (frame_len_smpl_ <= in_audio_ix_write_) ? 0 :
945       (frame_len_smpl_ - in_audio_ix_write_);
946 }
947 
SetUniqueID(const uint32_t id)948 void ACMGenericCodec::SetUniqueID(const uint32_t id) {
949   unique_id_ = id;
950 }
951 
952 // This function is replaced by codec specific functions for some codecs.
EncoderSampFreq(uint16_t * samp_freq_hz)953 int16_t ACMGenericCodec::EncoderSampFreq(uint16_t* samp_freq_hz) {
954   int32_t f;
955   f = ACMCodecDB::CodecFreq(codec_id_);
956   if (f < 0) {
957     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
958                  "EncoderSampFreq: codec frequency is negative");
959     return -1;
960   } else {
961     *samp_freq_hz = static_cast<uint16_t>(f);
962     return 0;
963   }
964 }
965 
ConfigISACBandwidthEstimator(const uint8_t,const uint16_t,const bool)966 int32_t ACMGenericCodec::ConfigISACBandwidthEstimator(
967     const uint8_t /* init_frame_size_msec */,
968     const uint16_t /* init_rate_bit_per_sec */,
969     const bool /* enforce_frame_size  */) {
970   WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
971                "The send-codec is not iSAC, failed to config iSAC bandwidth "
972                "estimator.");
973   return -1;
974 }
975 
SetISACMaxRate(const uint32_t)976 int32_t ACMGenericCodec::SetISACMaxRate(
977     const uint32_t /* max_rate_bit_per_sec */) {
978   WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
979                "The send-codec is not iSAC, failed to set iSAC max rate.");
980   return -1;
981 }
982 
SetISACMaxPayloadSize(const uint16_t)983 int32_t ACMGenericCodec::SetISACMaxPayloadSize(
984     const uint16_t /* max_payload_len_bytes */) {
985   WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
986                "The send-codec is not iSAC, failed to set iSAC max "
987                "payload-size.");
988   return -1;
989 }
990 
UpdateEncoderSampFreq(uint16_t)991 int16_t ACMGenericCodec::UpdateEncoderSampFreq(
992     uint16_t /* samp_freq_hz */) {
993   WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
994                "It is asked for a change in smapling frequency while the "
995                "current  send-codec supports only one sampling rate.");
996   return -1;
997 }
998 
REDPayloadISAC(const int32_t,const int16_t,uint8_t *,int16_t *)999 int16_t ACMGenericCodec::REDPayloadISAC(const int32_t /* isac_rate */,
1000                                         const int16_t /* isac_bw_estimate */,
1001                                         uint8_t* /* payload */,
1002                                         int16_t* /* payload_len_bytes */) {
1003   WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
1004                "Error: REDPayloadISAC is an iSAC specific function");
1005   return -1;
1006 }
1007 
1008 }  // namespace acm2
1009 
1010 }  // namespace webrtc
1011