1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
|
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/audio_coding/main/acm2/acm_g729.h"
#ifdef WEBRTC_CODEC_G729
// NOTE! G.729 is not included in the open-source package. Modify this file
// or your codec API to match the function calls and names of used G.729 API
// file.
#include "webrtc/modules/audio_coding/main/codecs/g729/interface/g729_interface.h"
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
#include "webrtc/modules/audio_coding/main/acm2/acm_receiver.h"
#include "webrtc/system_wrappers/interface/trace.h"
#endif
namespace webrtc {
namespace acm2 {
#ifndef WEBRTC_CODEC_G729
ACMG729::ACMG729(int16_t /* codec_id */) : encoder_inst_ptr_(NULL) {}
ACMG729::~ACMG729() { return; }
int16_t ACMG729::InternalEncode(uint8_t* /* bitstream */,
int16_t* /* bitstream_len_byte */) {
return -1;
}
int16_t ACMG729::EnableDTX() { return -1; }
int16_t ACMG729::DisableDTX() { return -1; }
int32_t ACMG729::ReplaceInternalDTXSafe(const bool /*replace_internal_dtx */) {
return -1;
}
int32_t ACMG729::IsInternalDTXReplacedSafe(bool* /* internal_dtx_replaced */) {
return -1;
}
int16_t ACMG729::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
return -1;
}
ACMGenericCodec* ACMG729::CreateInstance(void) { return NULL; }
int16_t ACMG729::InternalCreateEncoder() { return -1; }
void ACMG729::DestructEncoderSafe() { return; }
#else //===================== Actual Implementation =======================
ACMG729::ACMG729(int16_t codec_id)
: codec_id_(codec_id),
has_internal_dtx_(),
encoder_inst_ptr_(NULL) {}
ACMG729::~ACMG729() {
if (encoder_inst_ptr_ != NULL) {
// Delete encoder memory
WebRtcG729_FreeEnc(encoder_inst_ptr_);
encoder_inst_ptr_ = NULL;
}
return;
}
int16_t ACMG729::InternalEncode(uint8_t* bitstream,
int16_t* bitstream_len_byte) {
// Initialize before entering the loop
int16_t num_encoded_samples = 0;
int16_t tmp_len_byte = 0;
int16_t vad_decision = 0;
*bitstream_len_byte = 0;
while (num_encoded_samples < frame_len_smpl_) {
// Call G.729 encoder with pointer to encoder memory, input
// audio, number of samples and bitsream
tmp_len_byte = WebRtcG729_Encode(
encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], 80,
reinterpret_cast<int16_t*>(&(bitstream[*bitstream_len_byte])));
// increment the read index this tell the caller that how far
// we have gone forward in reading the audio buffer
in_audio_ix_read_ += 80;
// sanity check
if (tmp_len_byte < 0) {
// error has happened
*bitstream_len_byte = 0;
return -1;
}
// increment number of written bytes
*bitstream_len_byte += tmp_len_byte;
switch (tmp_len_byte) {
case 0: {
if (0 == num_encoded_samples) {
// this is the first 10 ms in this packet and there is
// no data generated, perhaps DTX is enabled and the
// codec is not generating any bit-stream for this 10 ms.
// we do not continue encoding this frame.
return 0;
}
break;
}
case 2: {
// check if G.729 internal DTX is enabled
if (has_internal_dtx_ && dtx_enabled_) {
vad_decision = 0;
for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
vad_label_[n] = vad_decision;
}
}
// we got a SID and have to send out this packet no matter
// how much audio we have encoded
return *bitstream_len_byte;
}
case 10: {
vad_decision = 1;
// this is a valid length just continue encoding
break;
}
default: {
return -1;
}
}
// update number of encoded samples
num_encoded_samples += 80;
}
// update VAD decision vector
if (has_internal_dtx_ && !vad_decision && dtx_enabled_) {
for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
vad_label_[n] = vad_decision;
}
}
// done encoding, return number of encoded bytes
return *bitstream_len_byte;
}
int16_t ACMG729::EnableDTX() {
if (dtx_enabled_) {
// DTX already enabled, do nothing
return 0;
} else if (encoder_exist_) {
// Re-init the G.729 encoder to turn on DTX
if (WebRtcG729_EncoderInit(encoder_inst_ptr_, 1) < 0) {
return -1;
}
dtx_enabled_ = true;
return 0;
} else {
return -1;
}
}
int16_t ACMG729::DisableDTX() {
if (!dtx_enabled_) {
// DTX already dissabled, do nothing
return 0;
} else if (encoder_exist_) {
// Re-init the G.729 decoder to turn off DTX
if (WebRtcG729_EncoderInit(encoder_inst_ptr_, 0) < 0) {
return -1;
}
dtx_enabled_ = false;
return 0;
} else {
// encoder doesn't exists, therefore disabling is harmless
return 0;
}
}
int32_t ACMG729::ReplaceInternalDTXSafe(const bool replace_internal_dtx) {
// This function is used to disable the G.729 built in DTX and use an
// external instead.
if (replace_internal_dtx == has_internal_dtx_) {
// Make sure we keep the DTX/VAD setting if possible
bool old_enable_dtx = dtx_enabled_;
bool old_enable_vad = vad_enabled_;
ACMVADMode old_mode = vad_mode_;
if (replace_internal_dtx) {
// Disable internal DTX before enabling external DTX
DisableDTX();
} else {
// Disable external DTX before enabling internal
ACMGenericCodec::DisableDTX();
}
has_internal_dtx_ = !replace_internal_dtx;
int16_t status = SetVADSafe(old_enable_dtx, old_enable_vad, old_mode);
// Check if VAD status has changed from inactive to active, or if error was
// reported
if (status == 1) {
vad_enabled_ = true;
return status;
} else if (status < 0) {
has_internal_dtx_ = replace_internal_dtx;
return -1;
}
}
return 0;
}
int32_t ACMG729::IsInternalDTXReplacedSafe(bool* internal_dtx_replaced) {
// Get status of wether DTX is replaced or not
*internal_dtx_replaced = !has_internal_dtx_;
return 0;
}
int16_t ACMG729::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
// Init G.729 encoder
return WebRtcG729_EncoderInit(encoder_inst_ptr_,
((codec_params->enable_dtx) ? 1 : 0));
}
ACMGenericCodec* ACMG729::CreateInstance(void) {
// Function not used
return NULL;
}
int16_t ACMG729::InternalCreateEncoder() {
// Create encoder memory
return WebRtcG729_CreateEnc(&encoder_inst_ptr_);
}
void ACMG729::DestructEncoderSafe() {
// Free encoder memory
encoder_exist_ = false;
encoder_initialized_ = false;
if (encoder_inst_ptr_ != NULL) {
WebRtcG729_FreeEnc(encoder_inst_ptr_);
encoder_inst_ptr_ = NULL;
}
}
#endif
} // namespace acm2
} // namespace webrtc
|