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 void ACMG729::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
62 #else //===================== Actual Implementation =======================
63 ACMG729::ACMG729(int16_t codec_id)
64 : codec_id_(codec_id),
66 encoder_inst_ptr_(NULL) {}
69 if (encoder_inst_ptr_ != NULL) {
70 // Delete encoder memory
71 WebRtcG729_FreeEnc(encoder_inst_ptr_);
72 encoder_inst_ptr_ = NULL;
77 int16_t ACMG729::InternalEncode(uint8_t* bitstream,
78 int16_t* bitstream_len_byte) {
79 // Initialize before entering the loop
80 int16_t num_encoded_samples = 0;
81 int16_t tmp_len_byte = 0;
82 int16_t vad_decision = 0;
83 *bitstream_len_byte = 0;
84 while (num_encoded_samples < frame_len_smpl_) {
85 // Call G.729 encoder with pointer to encoder memory, input
86 // audio, number of samples and bitsream
87 tmp_len_byte = WebRtcG729_Encode(
88 encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], 80,
89 reinterpret_cast<int16_t*>(&(bitstream[*bitstream_len_byte])));
91 // increment the read index this tell the caller that how far
92 // we have gone forward in reading the audio buffer
93 in_audio_ix_read_ += 80;
96 if (tmp_len_byte < 0) {
98 *bitstream_len_byte = 0;
102 // increment number of written bytes
103 *bitstream_len_byte += tmp_len_byte;
104 switch (tmp_len_byte) {
106 if (0 == num_encoded_samples) {
107 // this is the first 10 ms in this packet and there is
108 // no data generated, perhaps DTX is enabled and the
109 // codec is not generating any bit-stream for this 10 ms.
110 // we do not continue encoding this frame.
116 // check if G.729 internal DTX is enabled
117 if (has_internal_dtx_ && dtx_enabled_) {
119 for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
120 vad_label_[n] = vad_decision;
123 // we got a SID and have to send out this packet no matter
124 // how much audio we have encoded
125 return *bitstream_len_byte;
129 // this is a valid length just continue encoding
137 // update number of encoded samples
138 num_encoded_samples += 80;
141 // update VAD decision vector
142 if (has_internal_dtx_ && !vad_decision && dtx_enabled_) {
143 for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
144 vad_label_[n] = vad_decision;
148 // done encoding, return number of encoded bytes
149 return *bitstream_len_byte;
152 int16_t ACMG729::EnableDTX() {
154 // DTX already enabled, do nothing
156 } else if (encoder_exist_) {
157 // Re-init the G.729 encoder to turn on DTX
158 if (WebRtcG729_EncoderInit(encoder_inst_ptr_, 1) < 0) {
168 int16_t ACMG729::DisableDTX() {
170 // DTX already dissabled, do nothing
172 } else if (encoder_exist_) {
173 // Re-init the G.729 decoder to turn off DTX
174 if (WebRtcG729_EncoderInit(encoder_inst_ptr_, 0) < 0) {
177 dtx_enabled_ = false;
180 // encoder doesn't exists, therefore disabling is harmless
185 int32_t ACMG729::ReplaceInternalDTXSafe(const bool replace_internal_dtx) {
186 // This function is used to disable the G.729 built in DTX and use an
189 if (replace_internal_dtx == has_internal_dtx_) {
190 // Make sure we keep the DTX/VAD setting if possible
191 bool old_enable_dtx = dtx_enabled_;
192 bool old_enable_vad = vad_enabled_;
193 ACMVADMode old_mode = vad_mode_;
194 if (replace_internal_dtx) {
195 // Disable internal DTX before enabling external DTX
198 // Disable external DTX before enabling internal
199 ACMGenericCodec::DisableDTX();
201 has_internal_dtx_ = !replace_internal_dtx;
202 int16_t status = SetVADSafe(old_enable_dtx, old_enable_vad, old_mode);
203 // Check if VAD status has changed from inactive to active, or if error was
208 } else if (status < 0) {
209 has_internal_dtx_ = replace_internal_dtx;
216 int32_t ACMG729::IsInternalDTXReplacedSafe(bool* internal_dtx_replaced) {
217 // Get status of wether DTX is replaced or not
218 *internal_dtx_replaced = !has_internal_dtx_;
222 int16_t ACMG729::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
223 // Init G.729 encoder
224 return WebRtcG729_EncoderInit(encoder_inst_ptr_,
225 ((codec_params->enable_dtx) ? 1 : 0));
228 ACMGenericCodec* ACMG729::CreateInstance(void) {
233 int16_t ACMG729::InternalCreateEncoder() {
234 // Create encoder memory
235 return WebRtcG729_CreateEnc(&encoder_inst_ptr_);
238 void ACMG729::DestructEncoderSafe() {
239 // Free encoder memory
240 encoder_exist_ = false;
241 encoder_initialized_ = false;
242 if (encoder_inst_ptr_ != NULL) {
243 WebRtcG729_FreeEnc(encoder_inst_ptr_);
244 encoder_inst_ptr_ = NULL;
248 void ACMG729::InternalDestructEncoderInst(void* ptr_inst) {
249 if (ptr_inst != NULL) {
250 WebRtcG729_FreeEnc(static_cast<G729_encinst_t_*>(ptr_inst));
259 } // namespace webrtc