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_g729.h"
13 #ifdef WEBRTC_CODEC_G729
14 // NOTE! G.729 is not included in the open-source package. Modify this file
15 // or your codec API to match the function calls and names of used G.729 API
17 #include "webrtc/modules/audio_coding/main/codecs/g729/interface/g729_interface.h"
18 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
19 #include "webrtc/modules/audio_coding/main/acm2/acm_receiver.h"
20 #include "webrtc/system_wrappers/interface/trace.h"
27 #ifndef WEBRTC_CODEC_G729
29 ACMG729::ACMG729(int16_t /* codec_id */) : encoder_inst_ptr_(NULL) {}
31 ACMG729::~ACMG729() { return; }
33 int16_t ACMG729::InternalEncode(uint8_t* /* bitstream */,
34 int16_t* /* bitstream_len_byte */) {
38 int16_t ACMG729::EnableDTX() { return -1; }
40 int16_t ACMG729::DisableDTX() { return -1; }
42 int32_t ACMG729::ReplaceInternalDTXSafe(const bool /*replace_internal_dtx */) {
46 int32_t ACMG729::IsInternalDTXReplacedSafe(bool* /* internal_dtx_replaced */) {
50 int16_t ACMG729::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
54 ACMGenericCodec* ACMG729::CreateInstance(void) { return NULL; }
56 int16_t ACMG729::InternalCreateEncoder() { return -1; }
58 void ACMG729::DestructEncoderSafe() { return; }
60 #else //===================== Actual Implementation =======================
61 ACMG729::ACMG729(int16_t codec_id)
62 : codec_id_(codec_id),
64 encoder_inst_ptr_(NULL) {}
67 if (encoder_inst_ptr_ != NULL) {
68 // Delete encoder memory
69 WebRtcG729_FreeEnc(encoder_inst_ptr_);
70 encoder_inst_ptr_ = NULL;
75 int16_t ACMG729::InternalEncode(uint8_t* bitstream,
76 int16_t* bitstream_len_byte) {
77 // Initialize before entering the loop
78 int16_t num_encoded_samples = 0;
79 int16_t tmp_len_byte = 0;
80 int16_t vad_decision = 0;
81 *bitstream_len_byte = 0;
82 while (num_encoded_samples < frame_len_smpl_) {
83 // Call G.729 encoder with pointer to encoder memory, input
84 // audio, number of samples and bitsream
85 tmp_len_byte = WebRtcG729_Encode(
86 encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], 80,
87 reinterpret_cast<int16_t*>(&(bitstream[*bitstream_len_byte])));
89 // increment the read index this tell the caller that how far
90 // we have gone forward in reading the audio buffer
91 in_audio_ix_read_ += 80;
94 if (tmp_len_byte < 0) {
96 *bitstream_len_byte = 0;
100 // increment number of written bytes
101 *bitstream_len_byte += tmp_len_byte;
102 switch (tmp_len_byte) {
104 if (0 == num_encoded_samples) {
105 // this is the first 10 ms in this packet and there is
106 // no data generated, perhaps DTX is enabled and the
107 // codec is not generating any bit-stream for this 10 ms.
108 // we do not continue encoding this frame.
114 // check if G.729 internal DTX is enabled
115 if (has_internal_dtx_ && dtx_enabled_) {
117 for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
118 vad_label_[n] = vad_decision;
121 // we got a SID and have to send out this packet no matter
122 // how much audio we have encoded
123 return *bitstream_len_byte;
127 // this is a valid length just continue encoding
135 // update number of encoded samples
136 num_encoded_samples += 80;
139 // update VAD decision vector
140 if (has_internal_dtx_ && !vad_decision && dtx_enabled_) {
141 for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
142 vad_label_[n] = vad_decision;
146 // done encoding, return number of encoded bytes
147 return *bitstream_len_byte;
150 int16_t ACMG729::EnableDTX() {
152 // DTX already enabled, do nothing
154 } else if (encoder_exist_) {
155 // Re-init the G.729 encoder to turn on DTX
156 if (WebRtcG729_EncoderInit(encoder_inst_ptr_, 1) < 0) {
166 int16_t ACMG729::DisableDTX() {
168 // DTX already dissabled, do nothing
170 } else if (encoder_exist_) {
171 // Re-init the G.729 decoder to turn off DTX
172 if (WebRtcG729_EncoderInit(encoder_inst_ptr_, 0) < 0) {
175 dtx_enabled_ = false;
178 // encoder doesn't exists, therefore disabling is harmless
183 int32_t ACMG729::ReplaceInternalDTXSafe(const bool replace_internal_dtx) {
184 // This function is used to disable the G.729 built in DTX and use an
187 if (replace_internal_dtx == has_internal_dtx_) {
188 // Make sure we keep the DTX/VAD setting if possible
189 bool old_enable_dtx = dtx_enabled_;
190 bool old_enable_vad = vad_enabled_;
191 ACMVADMode old_mode = vad_mode_;
192 if (replace_internal_dtx) {
193 // Disable internal DTX before enabling external DTX
196 // Disable external DTX before enabling internal
197 ACMGenericCodec::DisableDTX();
199 has_internal_dtx_ = !replace_internal_dtx;
200 int16_t status = SetVADSafe(old_enable_dtx, old_enable_vad, old_mode);
201 // Check if VAD status has changed from inactive to active, or if error was
206 } else if (status < 0) {
207 has_internal_dtx_ = replace_internal_dtx;
214 int32_t ACMG729::IsInternalDTXReplacedSafe(bool* internal_dtx_replaced) {
215 // Get status of wether DTX is replaced or not
216 *internal_dtx_replaced = !has_internal_dtx_;
220 int16_t ACMG729::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
221 // Init G.729 encoder
222 return WebRtcG729_EncoderInit(encoder_inst_ptr_,
223 ((codec_params->enable_dtx) ? 1 : 0));
226 ACMGenericCodec* ACMG729::CreateInstance(void) {
231 int16_t ACMG729::InternalCreateEncoder() {
232 // Create encoder memory
233 return WebRtcG729_CreateEnc(&encoder_inst_ptr_);
236 void ACMG729::DestructEncoderSafe() {
237 // Free encoder memory
238 encoder_exist_ = false;
239 encoder_initialized_ = false;
240 if (encoder_inst_ptr_ != NULL) {
241 WebRtcG729_FreeEnc(encoder_inst_ptr_);
242 encoder_inst_ptr_ = NULL;
250 } // namespace webrtc