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_g7291.h" 12 13 #ifdef WEBRTC_CODEC_G729_1 14 // NOTE! G.729.1 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.1 API 16 // file. 17 #include "webrtc/modules/audio_coding/main/codecs/g7291/interface/g7291_interface.h" 18 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h" 19 #include "webrtc/system_wrappers/interface/trace.h" 20 #endif 21 22 namespace webrtc { 23 24 namespace acm2 { 25 26 #ifndef WEBRTC_CODEC_G729_1 27 28 ACMG729_1::ACMG729_1(int16_t /* codec_id */) 29 : encoder_inst_ptr_(NULL), 30 my_rate_(32000), 31 flag_8khz_(0), 32 flag_g729_mode_(0) { 33 return; 34 } 35 36 ACMG729_1::~ACMG729_1() { return; } 37 38 int16_t ACMG729_1::InternalEncode(uint8_t* /* bitstream */, 39 int16_t* /* bitstream_len_byte */) { 40 return -1; 41 } 42 43 int16_t ACMG729_1::InternalInitEncoder( 44 WebRtcACMCodecParams* /* codec_params */) { 45 return -1; 46 } 47 48 ACMGenericCodec* ACMG729_1::CreateInstance(void) { return NULL; } 49 50 int16_t ACMG729_1::InternalCreateEncoder() { return -1; } 51 52 void ACMG729_1::DestructEncoderSafe() { return; } 53 54 int16_t ACMG729_1::SetBitRateSafe(const int32_t /*rate*/) { return -1; } 55 56 #else //===================== Actual Implementation ======================= 57 58 struct G729_1_inst_t_; 59 60 ACMG729_1::ACMG729_1(int16_t codec_id) 61 : encoder_inst_ptr_(NULL), 62 my_rate_(32000), // Default rate. 63 flag_8khz_(0), 64 flag_g729_mode_(0) { 65 // TODO(tlegrand): We should add codec_id as a input variable to the 66 // constructor of ACMGenericCodec. 67 codec_id_ = codec_id; 68 return; 69 } 70 71 ACMG729_1::~ACMG729_1() { 72 if (encoder_inst_ptr_ != NULL) { 73 WebRtcG7291_Free(encoder_inst_ptr_); 74 encoder_inst_ptr_ = NULL; 75 } 76 return; 77 } 78 79 int16_t ACMG729_1::InternalEncode(uint8_t* bitstream, 80 int16_t* bitstream_len_byte) { 81 // Initialize before entering the loop 82 int16_t num_encoded_samples = 0; 83 *bitstream_len_byte = 0; 84 85 int16_t byte_length_frame = 0; 86 87 // Derive number of 20ms frames per encoded packet. 88 // [1,2,3] <=> [20,40,60]ms <=> [320,640,960] samples 89 int16_t num_20ms_frames = (frame_len_smpl_ / 320); 90 // Byte length for the frame. +1 is for rate information. 91 byte_length_frame = 92 my_rate_ / (8 * 50) * num_20ms_frames + (1 - flag_g729_mode_); 93 94 // The following might be revised if we have G729.1 Annex C (support for DTX); 95 do { 96 *bitstream_len_byte = WebRtcG7291_Encode( 97 encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], 98 reinterpret_cast<int16_t*>(bitstream), my_rate_, num_20ms_frames); 99 100 // increment the read index this tell the caller that how far 101 // we have gone forward in reading the audio buffer 102 in_audio_ix_read_ += 160; 103 104 // sanity check 105 if (*bitstream_len_byte < 0) { 106 // error has happened 107 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, 108 "InternalEncode: Encode error for G729_1"); 109 *bitstream_len_byte = 0; 110 return -1; 111 } 112 113 num_encoded_samples += 160; 114 } while (*bitstream_len_byte == 0); 115 116 // This criteria will change if we have Annex C. 117 if (*bitstream_len_byte != byte_length_frame) { 118 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, 119 "InternalEncode: Encode error for G729_1"); 120 *bitstream_len_byte = 0; 121 return -1; 122 } 123 124 if (num_encoded_samples != frame_len_smpl_) { 125 *bitstream_len_byte = 0; 126 return -1; 127 } 128 129 return *bitstream_len_byte; 130 } 131 132 int16_t ACMG729_1::InternalInitEncoder(WebRtcACMCodecParams* codec_params) { 133 // set the bit rate and initialize 134 my_rate_ = codec_params->codec_inst.rate; 135 return SetBitRateSafe((uint32_t)my_rate_); 136 } 137 138 ACMGenericCodec* ACMG729_1::CreateInstance(void) { return NULL; } 139 140 int16_t ACMG729_1::InternalCreateEncoder() { 141 if (WebRtcG7291_Create(&encoder_inst_ptr_) < 0) { 142 WEBRTC_TRACE(webrtc::kTraceError, 143 webrtc::kTraceAudioCoding, 144 unique_id_, 145 "InternalCreateEncoder: create encoder failed for G729_1"); 146 return -1; 147 } 148 return 0; 149 } 150 151 void ACMG729_1::DestructEncoderSafe() { 152 encoder_exist_ = false; 153 encoder_initialized_ = false; 154 if (encoder_inst_ptr_ != NULL) { 155 WebRtcG7291_Free(encoder_inst_ptr_); 156 encoder_inst_ptr_ = NULL; 157 } 158 } 159 160 int16_t ACMG729_1::SetBitRateSafe(const int32_t rate) { 161 // allowed rates: { 8000, 12000, 14000, 16000, 18000, 20000, 162 // 22000, 24000, 26000, 28000, 30000, 32000}; 163 // TODO(tlegrand): This check exists in one other place two. Should be 164 // possible to reuse code. 165 switch (rate) { 166 case 8000: { 167 my_rate_ = 8000; 168 break; 169 } 170 case 12000: { 171 my_rate_ = 12000; 172 break; 173 } 174 case 14000: { 175 my_rate_ = 14000; 176 break; 177 } 178 case 16000: { 179 my_rate_ = 16000; 180 break; 181 } 182 case 18000: { 183 my_rate_ = 18000; 184 break; 185 } 186 case 20000: { 187 my_rate_ = 20000; 188 break; 189 } 190 case 22000: { 191 my_rate_ = 22000; 192 break; 193 } 194 case 24000: { 195 my_rate_ = 24000; 196 break; 197 } 198 case 26000: { 199 my_rate_ = 26000; 200 break; 201 } 202 case 28000: { 203 my_rate_ = 28000; 204 break; 205 } 206 case 30000: { 207 my_rate_ = 30000; 208 break; 209 } 210 case 32000: { 211 my_rate_ = 32000; 212 break; 213 } 214 default: { 215 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, 216 "SetBitRateSafe: Invalid rate G729_1"); 217 return -1; 218 } 219 } 220 221 // Re-init with new rate 222 if (WebRtcG7291_EncoderInit(encoder_inst_ptr_, my_rate_, flag_8khz_, 223 flag_g729_mode_) >= 0) { 224 encoder_params_.codec_inst.rate = my_rate_; 225 return 0; 226 } else { 227 return -1; 228 } 229 } 230 231 #endif 232 233 } // namespace acm2 234 235 } // namespace webrtc 236