2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h"
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"
28 kMaxPLCParamsCNG = WEBRTC_CNG_MAX_LPC_ORDER,
29 kNewCNGNumLPCParams = 8
32 // Interval for sending new CNG parameters (SID frames) is 100 msec.
34 kCngSidIntervalMsec = 100
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.
40 ACMGenericCodec::ACMGenericCodec()
41 : in_audio_ix_write_(0),
43 in_timestamp_ix_write_(0),
46 frame_len_smpl_(-1), // invalid value
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),
59 num_lpc_params_(kNewCNGNumLPCParams),
60 sent_cn_previous_(false),
62 has_internal_fec_(false),
63 codec_wrapper_lock_(*RWLockWrapper::CreateRWLock()),
64 last_timestamp_(0xD87F3F9F),
66 // Initialize VAD vector.
67 for (int i = 0; i < MAX_FRAME_SIZE_10MSEC; i++) {
70 // Nullify memory for encoder and decoder, and set payload type to an
72 memset(&encoder_params_, 0, sizeof(WebRtcACMCodecParams));
73 encoder_params_.codec_inst.pltype = -1;
76 ACMGenericCodec::~ACMGenericCodec() {
77 // Check all the members which are pointers, and if they are not NULL
79 if (ptr_vad_inst_ != NULL) {
80 WebRtcVad_Free(ptr_vad_inst_);
83 if (in_audio_ != NULL) {
87 if (in_timestamp_ != NULL) {
88 delete[] in_timestamp_;
91 if (ptr_dtx_inst_ != NULL) {
92 WebRtcCng_FreeEnc(ptr_dtx_inst_);
95 delete &codec_wrapper_lock_;
98 int32_t ACMGenericCodec::Add10MsData(const uint32_t timestamp,
100 const uint16_t length_smpl,
101 const uint8_t audio_channel) {
102 WriteLockScoped wl(codec_wrapper_lock_);
103 return Add10MsDataSafe(timestamp, data, length_smpl, audio_channel);
106 int32_t ACMGenericCodec::Add10MsDataSafe(const uint32_t timestamp,
108 const uint16_t length_smpl,
109 const uint8_t audio_channel) {
110 // The codec expects to get data in correct sampling rate. Get the sampling
111 // frequency of the codec.
113 if (EncoderSampFreq(&plfreq_hz) < 0) {
117 // Sanity check to make sure the length of the input corresponds to 10 ms.
118 if ((plfreq_hz / 100) != length_smpl) {
119 // This is not 10 ms of audio, given the sampling frequency of the codec.
123 if (last_timestamp_ == timestamp) {
124 // Same timestamp as the last time, overwrite.
125 if ((in_audio_ix_write_ >= length_smpl * audio_channel) &&
126 (in_timestamp_ix_write_ > 0)) {
127 in_audio_ix_write_ -= length_smpl * audio_channel;
128 assert(in_timestamp_ix_write_ >= 0);
130 in_timestamp_ix_write_--;
131 assert(in_audio_ix_write_ >= 0);
132 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_,
133 "Adding 10ms with previous timestamp, overwriting the "
136 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_,
137 "Adding 10ms with previous timestamp, this will sound bad");
141 last_timestamp_ = timestamp;
143 // If the data exceeds the buffer size, we throw away the oldest data and
144 // add the newly received 10 msec at the end.
145 if ((in_audio_ix_write_ + length_smpl * audio_channel) >
146 AUDIO_BUFFER_SIZE_W16) {
147 // Get the number of samples to be overwritten.
148 int16_t missed_samples = in_audio_ix_write_ + length_smpl * audio_channel -
149 AUDIO_BUFFER_SIZE_W16;
151 // Move the data (overwrite the old data).
152 memmove(in_audio_, in_audio_ + missed_samples,
153 (AUDIO_BUFFER_SIZE_W16 - length_smpl * audio_channel) *
156 // Copy the new data.
157 memcpy(in_audio_ + (AUDIO_BUFFER_SIZE_W16 - length_smpl * audio_channel),
158 data, length_smpl * audio_channel * sizeof(int16_t));
160 // Get the number of 10 ms blocks which are overwritten.
161 int16_t missed_10ms_blocks =static_cast<int16_t>(
162 (missed_samples / audio_channel * 100) / plfreq_hz);
164 // Move the timestamps.
165 memmove(in_timestamp_, in_timestamp_ + missed_10ms_blocks,
166 (in_timestamp_ix_write_ - missed_10ms_blocks) * sizeof(uint32_t));
167 in_timestamp_ix_write_ -= missed_10ms_blocks;
168 assert(in_timestamp_ix_write_ >= 0);
170 in_timestamp_[in_timestamp_ix_write_] = timestamp;
171 in_timestamp_ix_write_++;
172 assert(in_timestamp_ix_write_ < TIMESTAMP_BUFFER_SIZE_W32);
175 in_audio_ix_write_ = AUDIO_BUFFER_SIZE_W16;
176 IncreaseNoMissedSamples(missed_samples);
177 return -missed_samples;
180 // Store the input data in our data buffer.
181 memcpy(in_audio_ + in_audio_ix_write_, data,
182 length_smpl * audio_channel * sizeof(int16_t));
183 in_audio_ix_write_ += length_smpl * audio_channel;
184 assert(in_timestamp_ix_write_ < TIMESTAMP_BUFFER_SIZE_W32);
186 in_timestamp_[in_timestamp_ix_write_] = timestamp;
187 in_timestamp_ix_write_++;
188 assert(in_timestamp_ix_write_ < TIMESTAMP_BUFFER_SIZE_W32);
192 bool ACMGenericCodec::HasFrameToEncode() const {
193 ReadLockScoped lockCodec(codec_wrapper_lock_);
194 if (in_audio_ix_write_ < frame_len_smpl_ * num_channels_)
199 int16_t ACMGenericCodec::Encode(uint8_t* bitstream,
200 int16_t* bitstream_len_byte,
202 WebRtcACMEncodingType* encoding_type) {
203 if (!HasFrameToEncode()) {
204 // There is not enough audio
206 *bitstream_len_byte = 0;
207 // Doesn't really matter what this parameter set to
208 *encoding_type = kNoEncoding;
211 WriteLockScoped lockCodec(codec_wrapper_lock_);
213 // Not all codecs accept the whole frame to be pushed into encoder at once.
214 // Some codecs needs to be feed with a specific number of samples different
215 // from the frame size. If this is the case, |myBasicCodingBlockSmpl| will
216 // report a number different from 0, and we will loop over calls to encoder
217 // further down, until we have encode a complete frame.
218 const int16_t my_basic_coding_block_smpl =
219 ACMCodecDB::BasicCodingBlock(codec_id_);
220 if (my_basic_coding_block_smpl < 0 || !encoder_initialized_ ||
222 // This should not happen, but in case it does, report no encoding done.
224 *bitstream_len_byte = 0;
225 *encoding_type = kNoEncoding;
226 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
227 "EncodeSafe: error, basic coding sample block is negative");
230 // This makes the internal encoder read from the beginning of the buffer.
231 in_audio_ix_read_ = 0;
232 *timestamp = in_timestamp_[0];
234 // Process the audio through VAD. The function will set |_vad_labels|.
235 // If VAD is disabled all entries in |_vad_labels| are set to ONE (active).
237 int16_t dtx_processed_samples = 0;
238 status = ProcessFrameVADDTX(bitstream, bitstream_len_byte,
239 &dtx_processed_samples);
242 *bitstream_len_byte = 0;
243 *encoding_type = kNoEncoding;
245 if (dtx_processed_samples > 0) {
246 // Dtx have processed some samples, and even if a bit-stream is generated
247 // we should not do any encoding (normally there won't be enough data).
249 // Setting the following makes sure that the move of audio data and
250 // timestamps done correctly.
251 in_audio_ix_read_ = dtx_processed_samples;
252 // This will let the owner of ACMGenericCodec to know that the
253 // generated bit-stream is DTX to use correct payload type.
254 uint16_t samp_freq_hz;
255 EncoderSampFreq(&samp_freq_hz);
256 if (samp_freq_hz == 8000) {
257 *encoding_type = kPassiveDTXNB;
258 } else if (samp_freq_hz == 16000) {
259 *encoding_type = kPassiveDTXWB;
260 } else if (samp_freq_hz == 32000) {
261 *encoding_type = kPassiveDTXSWB;
262 } else if (samp_freq_hz == 48000) {
263 *encoding_type = kPassiveDTXFB;
266 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
267 "EncodeSafe: Wrong sampling frequency for DTX.");
270 // Transport empty frame if we have an empty bitstream.
271 if ((*bitstream_len_byte == 0) &&
272 (sent_cn_previous_ ||
273 ((in_audio_ix_write_ - in_audio_ix_read_) <= 0))) {
274 // Makes sure we transmit an empty frame.
275 *bitstream_len_byte = 1;
276 *encoding_type = kNoEncoding;
278 sent_cn_previous_ = true;
280 // We should encode the audio frame. Either VAD and/or DTX is off, or the
281 // audio was considered "active".
283 sent_cn_previous_ = false;
284 if (my_basic_coding_block_smpl == 0) {
285 // This codec can handle all allowed frame sizes as basic coding block.
286 status = InternalEncode(bitstream, bitstream_len_byte);
288 // TODO(tlegrand): Maybe reseting the encoder to be fresh for the next
290 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding,
291 unique_id_, "EncodeSafe: error in internal_encode");
292 *bitstream_len_byte = 0;
293 *encoding_type = kNoEncoding;
296 // A basic-coding-block for this codec is defined so we loop over the
297 // audio with the steps of the basic-coding-block.
298 int16_t tmp_bitstream_len_byte;
300 // Reset the variables which will be incremented in the loop.
301 *bitstream_len_byte = 0;
304 status = InternalEncode(&bitstream[*bitstream_len_byte],
305 &tmp_bitstream_len_byte);
306 *bitstream_len_byte += tmp_bitstream_len_byte;
308 // Guard Against errors and too large payloads.
309 if ((status < 0) || (*bitstream_len_byte > MAX_PAYLOAD_SIZE_BYTE)) {
310 // Error has happened, and even if we are in the middle of a full
311 // frame we have to exit. Before exiting, whatever bits are in the
312 // buffer are probably corrupted, so we ignore them.
313 *bitstream_len_byte = 0;
314 *encoding_type = kNoEncoding;
315 // We might have come here because of the second condition.
317 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding,
318 unique_id_, "EncodeSafe: error in InternalEncode");
319 // break from the loop
322 done = in_audio_ix_read_ >= frame_len_smpl_ * num_channels_;
326 *encoding_type = (vad_label_[0] == 1) ? kActiveNormalEncoded :
327 kPassiveNormalEncoded;
328 // Transport empty frame if we have an empty bitstream.
329 if ((*bitstream_len_byte == 0) &&
330 ((in_audio_ix_write_ - in_audio_ix_read_) <= 0)) {
331 // Makes sure we transmit an empty frame.
332 *bitstream_len_byte = 1;
333 *encoding_type = kNoEncoding;
339 // Move the timestamp buffer according to the number of 10 ms blocks
341 uint16_t samp_freq_hz;
342 EncoderSampFreq(&samp_freq_hz);
343 int16_t num_10ms_blocks = static_cast<int16_t>(
344 (in_audio_ix_read_ / num_channels_ * 100) / samp_freq_hz);
345 if (in_timestamp_ix_write_ > num_10ms_blocks) {
346 memmove(in_timestamp_, in_timestamp_ + num_10ms_blocks,
347 (in_timestamp_ix_write_ - num_10ms_blocks) * sizeof(int32_t));
349 in_timestamp_ix_write_ -= num_10ms_blocks;
350 assert(in_timestamp_ix_write_ >= 0);
352 // Remove encoded audio and move next audio to be encoded to the beginning
353 // of the buffer. Accordingly, adjust the read and write indices.
354 if (in_audio_ix_read_ < in_audio_ix_write_) {
355 memmove(in_audio_, &in_audio_[in_audio_ix_read_],
356 (in_audio_ix_write_ - in_audio_ix_read_) * sizeof(int16_t));
358 in_audio_ix_write_ -= in_audio_ix_read_;
359 in_audio_ix_read_ = 0;
360 return (status < 0) ? (-1) : (*bitstream_len_byte);
363 bool ACMGenericCodec::EncoderInitialized() {
364 ReadLockScoped rl(codec_wrapper_lock_);
365 return encoder_initialized_;
368 int16_t ACMGenericCodec::EncoderParams(WebRtcACMCodecParams* enc_params) {
369 ReadLockScoped rl(codec_wrapper_lock_);
370 return EncoderParamsSafe(enc_params);
373 int16_t ACMGenericCodec::EncoderParamsSafe(WebRtcACMCodecParams* enc_params) {
374 // Codec parameters are valid only if the encoder is initialized.
375 if (encoder_initialized_) {
376 int32_t current_rate;
377 memcpy(enc_params, &encoder_params_, sizeof(WebRtcACMCodecParams));
378 current_rate = enc_params->codec_inst.rate;
379 CurrentRate(¤t_rate);
380 enc_params->codec_inst.rate = current_rate;
383 enc_params->codec_inst.plname[0] = '\0';
384 enc_params->codec_inst.pltype = -1;
385 enc_params->codec_inst.pacsize = 0;
386 enc_params->codec_inst.rate = 0;
387 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
388 "EncoderParamsSafe: error, encoder not initialized");
393 int16_t ACMGenericCodec::ResetEncoder() {
394 WriteLockScoped lockCodec(codec_wrapper_lock_);
395 return ResetEncoderSafe();
398 int16_t ACMGenericCodec::ResetEncoderSafe() {
399 if (!encoder_exist_ || !encoder_initialized_) {
400 // We don't reset if encoder doesn't exists or isn't initialized yet.
404 in_audio_ix_write_ = 0;
405 in_audio_ix_read_ = 0;
406 in_timestamp_ix_write_ = 0;
407 num_missed_samples_ = 0;
408 memset(in_audio_, 0, AUDIO_BUFFER_SIZE_W16 * sizeof(int16_t));
409 memset(in_timestamp_, 0, TIMESTAMP_BUFFER_SIZE_W32 * sizeof(int32_t));
411 // Store DTX/VAD parameters.
412 bool enable_vad = vad_enabled_;
413 bool enable_dtx = dtx_enabled_;
414 ACMVADMode mode = vad_mode_;
416 // Reset the encoder.
417 if (InternalResetEncoder() < 0) {
418 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
419 "ResetEncoderSafe: error in reset encoder");
423 // Disable DTX & VAD to delete the states and have a fresh start.
428 int status = SetVADSafe(&enable_dtx, &enable_vad, &mode);
429 dtx_enabled_ = enable_dtx;
430 vad_enabled_ = enable_vad;
435 int16_t ACMGenericCodec::InternalResetEncoder() {
436 // Call the codecs internal encoder initialization/reset function.
437 return InternalInitEncoder(&encoder_params_);
440 int16_t ACMGenericCodec::InitEncoder(WebRtcACMCodecParams* codec_params,
441 bool force_initialization) {
442 WriteLockScoped lockCodec(codec_wrapper_lock_);
443 return InitEncoderSafe(codec_params, force_initialization);
446 int16_t ACMGenericCodec::InitEncoderSafe(WebRtcACMCodecParams* codec_params,
447 bool force_initialization) {
448 // Check if we got a valid set of parameters.
450 int codec_number = ACMCodecDB::CodecNumber(codec_params->codec_inst,
452 assert(codec_number >= 0);
454 // Check if the parameters are for this codec.
455 if ((codec_id_ >= 0) && (codec_id_ != codec_number) &&
456 (codec_id_ != mirrorID)) {
457 // The current codec is not the same as the one given by codec_params.
458 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
459 "InitEncoderSafe: current codec is not the same as the one "
460 "given by codec_params");
464 if (encoder_initialized_ && !force_initialization) {
465 // The encoder is already initialized, and we don't want to force
470 if (!encoder_exist_) {
471 // New encoder, start with creating.
472 encoder_initialized_ = false;
473 status = CreateEncoder();
475 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
476 "InitEncoderSafe: cannot create encoder");
479 encoder_exist_ = true;
482 frame_len_smpl_ = codec_params->codec_inst.pacsize;
483 num_channels_ = codec_params->codec_inst.channels;
484 status = InternalInitEncoder(codec_params);
486 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
487 "InitEncoderSafe: error in init encoder");
488 encoder_initialized_ = false;
491 // TODO(turajs): Move these allocations to the constructor issue 2445.
492 // Store encoder parameters.
493 memcpy(&encoder_params_, codec_params, sizeof(WebRtcACMCodecParams));
494 encoder_initialized_ = true;
495 if (in_audio_ == NULL) {
496 in_audio_ = new int16_t[AUDIO_BUFFER_SIZE_W16];
498 if (in_timestamp_ == NULL) {
499 in_timestamp_ = new uint32_t[TIMESTAMP_BUFFER_SIZE_W32];
503 // Fresh start of audio buffer.
504 memset(in_audio_, 0, sizeof(*in_audio_) * AUDIO_BUFFER_SIZE_W16);
505 memset(in_timestamp_, 0, sizeof(*in_timestamp_) * TIMESTAMP_BUFFER_SIZE_W32);
506 in_audio_ix_write_ = 0;
507 in_audio_ix_read_ = 0;
508 in_timestamp_ix_write_ = 0;
510 return SetVADSafe(&codec_params->enable_dtx, &codec_params->enable_vad,
511 &codec_params->vad_mode);
514 void ACMGenericCodec::ResetNoMissedSamples() {
515 WriteLockScoped cs(codec_wrapper_lock_);
516 num_missed_samples_ = 0;
519 void ACMGenericCodec::IncreaseNoMissedSamples(const int16_t num_samples) {
520 num_missed_samples_ += num_samples;
523 // Get the number of missed samples, this can be public.
524 uint32_t ACMGenericCodec::NoMissedSamples() const {
525 ReadLockScoped cs(codec_wrapper_lock_);
526 return num_missed_samples_;
529 void ACMGenericCodec::DestructEncoder() {
530 WriteLockScoped wl(codec_wrapper_lock_);
532 // Disable VAD and delete the instance.
533 if (ptr_vad_inst_ != NULL) {
534 WebRtcVad_Free(ptr_vad_inst_);
535 ptr_vad_inst_ = NULL;
537 vad_enabled_ = false;
538 vad_mode_ = VADNormal;
540 // Disable DTX and delete the instance.
541 dtx_enabled_ = false;
542 if (ptr_dtx_inst_ != NULL) {
543 WebRtcCng_FreeEnc(ptr_dtx_inst_);
544 ptr_dtx_inst_ = NULL;
546 num_lpc_params_ = kNewCNGNumLPCParams;
548 DestructEncoderSafe();
551 int16_t ACMGenericCodec::SetBitRate(const int32_t bitrate_bps) {
552 WriteLockScoped wl(codec_wrapper_lock_);
553 return SetBitRateSafe(bitrate_bps);
556 int16_t ACMGenericCodec::SetBitRateSafe(const int32_t bitrate_bps) {
557 // If the codec can change the bit-rate this function is overloaded.
558 // Otherwise the only acceptable value is the one that is in the database.
559 CodecInst codec_params;
560 if (ACMCodecDB::Codec(codec_id_, &codec_params) < 0) {
561 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
562 "SetBitRateSafe: error in ACMCodecDB::Codec");
565 if (codec_params.rate != bitrate_bps) {
566 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
567 "SetBitRateSafe: rate value is not acceptable");
574 // iSAC specific functions:
575 int32_t ACMGenericCodec::GetEstimatedBandwidth() {
576 WriteLockScoped wl(codec_wrapper_lock_);
577 return GetEstimatedBandwidthSafe();
580 int32_t ACMGenericCodec::GetEstimatedBandwidthSafe() {
581 // All codecs but iSAC will return -1.
585 int32_t ACMGenericCodec::SetEstimatedBandwidth(int32_t estimated_bandwidth) {
586 WriteLockScoped wl(codec_wrapper_lock_);
587 return SetEstimatedBandwidthSafe(estimated_bandwidth);
590 int32_t ACMGenericCodec::SetEstimatedBandwidthSafe(
591 int32_t /*estimated_bandwidth*/) {
592 // All codecs but iSAC will return -1.
595 // End of iSAC specific functions.
597 int32_t ACMGenericCodec::GetRedPayload(uint8_t* red_payload,
598 int16_t* payload_bytes) {
599 WriteLockScoped wl(codec_wrapper_lock_);
600 return GetRedPayloadSafe(red_payload, payload_bytes);
603 int32_t ACMGenericCodec::GetRedPayloadSafe(uint8_t* /* red_payload */,
604 int16_t* /* payload_bytes */) {
605 return -1; // Do nothing by default.
608 int16_t ACMGenericCodec::CreateEncoder() {
610 if (!encoder_exist_) {
611 status = InternalCreateEncoder();
612 // We just created the codec and obviously it is not initialized.
613 encoder_initialized_ = false;
616 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
617 "CreateEncoder: error in internal create encoder");
618 encoder_exist_ = false;
620 encoder_exist_ = true;
625 void ACMGenericCodec::DestructEncoderInst(void* ptr_inst) {
626 if (ptr_inst != NULL) {
627 WriteLockScoped lockCodec(codec_wrapper_lock_);
628 InternalDestructEncoderInst(ptr_inst);
632 uint32_t ACMGenericCodec::EarliestTimestamp() const {
633 ReadLockScoped cs(codec_wrapper_lock_);
634 return in_timestamp_[0];
637 int16_t ACMGenericCodec::SetVAD(bool* enable_dtx,
640 WriteLockScoped cs(codec_wrapper_lock_);
641 return SetVADSafe(enable_dtx, enable_vad, mode);
644 int16_t ACMGenericCodec::SetVADSafe(bool* enable_dtx,
647 if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "OPUS") ||
648 encoder_params_.codec_inst.channels == 2 ) {
649 // VAD/DTX is not supported for Opus (even if sending mono), or other
659 // Make G729 AnnexB a special case.
660 if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "G729")
661 && !has_internal_dtx_) {
662 if (ACMGenericCodec::EnableDTX() < 0) {
663 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
664 "SetVADSafe: error in enable DTX");
666 *enable_vad = vad_enabled_;
670 if (EnableDTX() < 0) {
671 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
672 "SetVADSafe: error in enable DTX");
674 *enable_vad = vad_enabled_;
679 // If codec does not have internal DTX (normal case) enabling DTX requires
680 // an active VAD. '*enable_dtx == true' overwrites VAD status.
681 // If codec has internal DTX, practically we don't need WebRtc VAD, however,
682 // we let the user to turn it on if they need call-backs on silence.
683 if (!has_internal_dtx_) {
684 // DTX is enabled, and VAD will be activated.
688 // Make G729 AnnexB a special case.
689 if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "G729")
690 && !has_internal_dtx_) {
691 ACMGenericCodec::DisableDTX();
699 int16_t status = (*enable_vad) ? EnableVAD(*mode) : DisableVAD();
701 // Failed to set VAD, disable DTX.
702 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
703 "SetVADSafe: error in enable VAD");
711 int16_t ACMGenericCodec::EnableDTX() {
712 if (has_internal_dtx_) {
713 // We should not be here if we have internal DTX this function should be
714 // overloaded by the derived class in this case.
718 if (WebRtcCng_CreateEnc(&ptr_dtx_inst_) < 0) {
719 ptr_dtx_inst_ = NULL;
723 EncoderSampFreq(&freq_hz);
724 if (WebRtcCng_InitEnc(ptr_dtx_inst_, freq_hz, kCngSidIntervalMsec,
725 num_lpc_params_) < 0) {
726 // Couldn't initialize, has to return -1, and free the memory.
727 WebRtcCng_FreeEnc(ptr_dtx_inst_);
728 ptr_dtx_inst_ = NULL;
736 int16_t ACMGenericCodec::DisableDTX() {
737 if (has_internal_dtx_) {
738 // We should not be here if we have internal DTX this function should be
739 // overloaded by the derived class in this case.
742 if (ptr_dtx_inst_ != NULL) {
743 WebRtcCng_FreeEnc(ptr_dtx_inst_);
744 ptr_dtx_inst_ = NULL;
746 dtx_enabled_ = false;
750 int16_t ACMGenericCodec::EnableVAD(ACMVADMode mode) {
751 if ((mode < VADNormal) || (mode > VADVeryAggr)) {
752 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
753 "EnableVAD: error in VAD mode range");
758 if (WebRtcVad_Create(&ptr_vad_inst_) < 0) {
759 ptr_vad_inst_ = NULL;
760 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
761 "EnableVAD: error in create VAD");
764 if (WebRtcVad_Init(ptr_vad_inst_) < 0) {
765 WebRtcVad_Free(ptr_vad_inst_);
766 ptr_vad_inst_ = NULL;
767 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
768 "EnableVAD: error in init VAD");
773 // Set the VAD mode to the given value.
774 if (WebRtcVad_set_mode(ptr_vad_inst_, mode) < 0) {
775 // We failed to set the mode and we have to return -1. If we already have a
776 // working VAD (vad_enabled_ == true) then we leave it to work. Otherwise,
777 // the following will be executed.
779 // We just created the instance but cannot set the mode we have to free
781 WebRtcVad_Free(ptr_vad_inst_);
782 ptr_vad_inst_ = NULL;
784 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_,
785 "EnableVAD: failed to set the VAD mode");
793 int16_t ACMGenericCodec::DisableVAD() {
794 if (ptr_vad_inst_ != NULL) {
795 WebRtcVad_Free(ptr_vad_inst_);
796 ptr_vad_inst_ = NULL;
798 vad_enabled_ = false;
802 int32_t ACMGenericCodec::ReplaceInternalDTX(const bool replace_internal_dtx) {
803 WriteLockScoped cs(codec_wrapper_lock_);
804 return ReplaceInternalDTXSafe(replace_internal_dtx);
807 int32_t ACMGenericCodec::ReplaceInternalDTXSafe(
808 const bool /* replace_internal_dtx */) {
812 int32_t ACMGenericCodec::IsInternalDTXReplaced(bool* internal_dtx_replaced) {
813 WriteLockScoped cs(codec_wrapper_lock_);
814 return IsInternalDTXReplacedSafe(internal_dtx_replaced);
817 int32_t ACMGenericCodec::IsInternalDTXReplacedSafe(
818 bool* internal_dtx_replaced) {
819 *internal_dtx_replaced = false;
823 int16_t ACMGenericCodec::ProcessFrameVADDTX(uint8_t* bitstream,
824 int16_t* bitstream_len_byte,
825 int16_t* samples_processed) {
827 // VAD not enabled, set all |vad_lable_[]| to 1 (speech detected).
828 for (int n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
831 *samples_processed = 0;
836 EncoderSampFreq(&freq_hz);
838 // Calculate number of samples in 10 ms blocks, and number ms in one frame.
839 int16_t samples_in_10ms = static_cast<int16_t>(freq_hz / 100);
840 int32_t frame_len_ms = static_cast<int32_t>(frame_len_smpl_) * 1000 / freq_hz;
843 // Vector for storing maximum 30 ms of mono audio at 48 kHz.
846 // Calculate number of VAD-blocks to process, and number of samples in each
848 int num_samples_to_process[2];
849 if (frame_len_ms == 40) {
850 // 20 ms in each VAD block.
851 num_samples_to_process[0] = num_samples_to_process[1] = 2 * samples_in_10ms;
853 // For 10-30 ms framesizes, second VAD block will be size zero ms,
854 // for 50 and 60 ms first VAD block will be 30 ms.
855 num_samples_to_process[0] =
856 (frame_len_ms > 30) ? 3 * samples_in_10ms : frame_len_smpl_;
857 num_samples_to_process[1] = frame_len_smpl_ - num_samples_to_process[0];
861 int loops = (num_samples_to_process[1] > 0) ? 2 : 1;
862 for (int i = 0; i < loops; i++) {
863 // TODO(turajs): Do we need to care about VAD together with stereo?
864 // If stereo, calculate mean of the two channels.
865 if (num_channels_ == 2) {
866 for (int j = 0; j < num_samples_to_process[i]; j++) {
867 audio[j] = (in_audio_[(offset + j) * 2] +
868 in_audio_[(offset + j) * 2 + 1]) / 2;
870 offset = num_samples_to_process[0];
872 // Mono, copy data from in_audio_ to continue work on.
873 memcpy(audio, in_audio_, sizeof(int16_t) * num_samples_to_process[i]);
877 status = static_cast<int16_t>(WebRtcVad_Process(ptr_vad_inst_,
878 static_cast<int>(freq_hz),
880 num_samples_to_process[i]));
881 vad_label_[i] = status;
884 // This will force that the data be removed from the buffer.
885 *samples_processed += num_samples_to_process[i];
889 // If VAD decision non-active, update DTX. NOTE! We only do this if the
890 // first part of a frame gets the VAD decision "inactive". Otherwise DTX
891 // might say it is time to transmit SID frame, but we will encode the whole
892 // frame, because the first part is active.
893 *samples_processed = 0;
894 if ((status == 0) && (i == 0) && dtx_enabled_ && !has_internal_dtx_) {
895 int16_t bitstream_len;
896 int num_10ms_frames = num_samples_to_process[i] / samples_in_10ms;
897 *bitstream_len_byte = 0;
898 for (int n = 0; n < num_10ms_frames; n++) {
899 // This block is (passive) && (vad enabled). If first CNG after
900 // speech, force SID by setting last parameter to "1".
901 status = WebRtcCng_Encode(ptr_dtx_inst_, &audio[n * samples_in_10ms],
902 samples_in_10ms, bitstream, &bitstream_len,
908 // Update previous frame was CNG.
911 *samples_processed += samples_in_10ms * num_channels_;
913 // |bitstream_len_byte| will only be > 0 once per 100 ms.
914 *bitstream_len_byte += bitstream_len;
917 // Check if all samples got processed by the DTX.
918 if (*samples_processed != num_samples_to_process[i] * num_channels_) {
919 // Set to zero since something went wrong. Shouldn't happen.
920 *samples_processed = 0;
923 // Update previous frame was not CNG.
927 if (*samples_processed > 0) {
928 // The block contains inactive speech, and is processed by DTX.
929 // Discontinue running VAD.
937 int16_t ACMGenericCodec::SamplesLeftToEncode() {
938 ReadLockScoped rl(codec_wrapper_lock_);
939 return (frame_len_smpl_ <= in_audio_ix_write_) ? 0 :
940 (frame_len_smpl_ - in_audio_ix_write_);
943 void ACMGenericCodec::SetUniqueID(const uint32_t id) {
947 // This function is replaced by codec specific functions for some codecs.
948 int16_t ACMGenericCodec::EncoderSampFreq(uint16_t* samp_freq_hz) {
950 f = ACMCodecDB::CodecFreq(codec_id_);
952 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
953 "EncoderSampFreq: codec frequency is negative");
956 *samp_freq_hz = static_cast<uint16_t>(f);
961 int32_t ACMGenericCodec::ConfigISACBandwidthEstimator(
962 const uint8_t /* init_frame_size_msec */,
963 const uint16_t /* init_rate_bit_per_sec */,
964 const bool /* enforce_frame_size */) {
965 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
966 "The send-codec is not iSAC, failed to config iSAC bandwidth "
971 int32_t ACMGenericCodec::SetISACMaxRate(
972 const uint32_t /* max_rate_bit_per_sec */) {
973 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
974 "The send-codec is not iSAC, failed to set iSAC max rate.");
978 int32_t ACMGenericCodec::SetISACMaxPayloadSize(
979 const uint16_t /* max_payload_len_bytes */) {
980 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
981 "The send-codec is not iSAC, failed to set iSAC max "
986 int16_t ACMGenericCodec::UpdateEncoderSampFreq(
987 uint16_t /* samp_freq_hz */) {
988 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
989 "It is asked for a change in smapling frequency while the "
990 "current send-codec supports only one sampling rate.");
994 int16_t ACMGenericCodec::REDPayloadISAC(const int32_t /* isac_rate */,
995 const int16_t /* isac_bw_estimate */,
996 uint8_t* /* payload */,
997 int16_t* /* payload_len_bytes */) {
998 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
999 "Error: REDPayloadISAC is an iSAC specific function");
1003 int ACMGenericCodec::SetOpusMaxBandwidth(int /* max_bandwidth */) {
1004 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
1005 "The send-codec is not Opus, failed to set maximum bandwidth.");
1011 } // namespace webrtc