Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / main / acm2 / acm_g729.cc
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_g729.h"
12
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
16 // file.
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"
21 #endif
22
23 namespace webrtc {
24
25 namespace acm2 {
26
27 #ifndef WEBRTC_CODEC_G729
28
29 ACMG729::ACMG729(int16_t /* codec_id */) : encoder_inst_ptr_(NULL) {}
30
31 ACMG729::~ACMG729() { return; }
32
33 int16_t ACMG729::InternalEncode(uint8_t* /* bitstream */,
34                                 int16_t* /* bitstream_len_byte */) {
35   return -1;
36 }
37
38 int16_t ACMG729::EnableDTX() { return -1; }
39
40 int16_t ACMG729::DisableDTX() { return -1; }
41
42 int32_t ACMG729::ReplaceInternalDTXSafe(const bool /*replace_internal_dtx */) {
43   return -1;
44 }
45
46 int32_t ACMG729::IsInternalDTXReplacedSafe(bool* /* internal_dtx_replaced */) {
47   return -1;
48 }
49
50 int16_t ACMG729::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
51   return -1;
52 }
53
54 ACMGenericCodec* ACMG729::CreateInstance(void) { return NULL; }
55
56 int16_t ACMG729::InternalCreateEncoder() { return -1; }
57
58 void ACMG729::DestructEncoderSafe() { return; }
59
60 #else  //===================== Actual Implementation =======================
61 ACMG729::ACMG729(int16_t codec_id)
62     : codec_id_(codec_id),
63       has_internal_dtx_(),
64       encoder_inst_ptr_(NULL) {}
65
66 ACMG729::~ACMG729() {
67   if (encoder_inst_ptr_ != NULL) {
68     // Delete encoder memory
69     WebRtcG729_FreeEnc(encoder_inst_ptr_);
70     encoder_inst_ptr_ = NULL;
71   }
72   return;
73 }
74
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])));
88
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;
92
93     // sanity check
94     if (tmp_len_byte < 0) {
95       // error has happened
96       *bitstream_len_byte = 0;
97       return -1;
98     }
99
100     // increment number of written bytes
101     *bitstream_len_byte += tmp_len_byte;
102     switch (tmp_len_byte) {
103       case 0: {
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.
109           return 0;
110         }
111         break;
112       }
113       case 2: {
114         // check if G.729 internal DTX is enabled
115         if (has_internal_dtx_ && dtx_enabled_) {
116           vad_decision = 0;
117           for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
118             vad_label_[n] = vad_decision;
119           }
120         }
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;
124       }
125       case 10: {
126         vad_decision = 1;
127         // this is a valid length just continue encoding
128         break;
129       }
130       default: {
131         return -1;
132       }
133     }
134
135     // update number of encoded samples
136     num_encoded_samples += 80;
137   }
138
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;
143     }
144   }
145
146   // done encoding, return number of encoded bytes
147   return *bitstream_len_byte;
148 }
149
150 int16_t ACMG729::EnableDTX() {
151   if (dtx_enabled_) {
152     // DTX already enabled, do nothing
153     return 0;
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) {
157       return -1;
158     }
159     dtx_enabled_ = true;
160     return 0;
161   } else {
162     return -1;
163   }
164 }
165
166 int16_t ACMG729::DisableDTX() {
167   if (!dtx_enabled_) {
168     // DTX already dissabled, do nothing
169     return 0;
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) {
173       return -1;
174     }
175     dtx_enabled_ = false;
176     return 0;
177   } else {
178     // encoder doesn't exists, therefore disabling is harmless
179     return 0;
180   }
181 }
182
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
185   // external instead.
186
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
194       DisableDTX();
195     } else {
196       // Disable external DTX before enabling internal
197       ACMGenericCodec::DisableDTX();
198     }
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
202     // reported
203     if (status == 1) {
204       vad_enabled_ = true;
205       return status;
206     } else if (status < 0) {
207       has_internal_dtx_ = replace_internal_dtx;
208       return -1;
209     }
210   }
211   return 0;
212 }
213
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_;
217   return 0;
218 }
219
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));
224 }
225
226 ACMGenericCodec* ACMG729::CreateInstance(void) {
227   // Function not used
228   return NULL;
229 }
230
231 int16_t ACMG729::InternalCreateEncoder() {
232   // Create encoder memory
233   return WebRtcG729_CreateEnc(&encoder_inst_ptr_);
234 }
235
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;
243   }
244 }
245
246 #endif
247
248 }  // namespace acm2
249
250 }  // namespace webrtc