- add third_party src.
[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 void ACMG729::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
61
62 #else  //===================== Actual Implementation =======================
63 ACMG729::ACMG729(int16_t codec_id)
64     : codec_id_(codec_id),
65       has_internal_dtx_(),
66       encoder_inst_ptr_(NULL) {}
67
68 ACMG729::~ACMG729() {
69   if (encoder_inst_ptr_ != NULL) {
70     // Delete encoder memory
71     WebRtcG729_FreeEnc(encoder_inst_ptr_);
72     encoder_inst_ptr_ = NULL;
73   }
74   return;
75 }
76
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])));
90
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;
94
95     // sanity check
96     if (tmp_len_byte < 0) {
97       // error has happened
98       *bitstream_len_byte = 0;
99       return -1;
100     }
101
102     // increment number of written bytes
103     *bitstream_len_byte += tmp_len_byte;
104     switch (tmp_len_byte) {
105       case 0: {
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.
111           return 0;
112         }
113         break;
114       }
115       case 2: {
116         // check if G.729 internal DTX is enabled
117         if (has_internal_dtx_ && dtx_enabled_) {
118           vad_decision = 0;
119           for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
120             vad_label_[n] = vad_decision;
121           }
122         }
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;
126       }
127       case 10: {
128         vad_decision = 1;
129         // this is a valid length just continue encoding
130         break;
131       }
132       default: {
133         return -1;
134       }
135     }
136
137     // update number of encoded samples
138     num_encoded_samples += 80;
139   }
140
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;
145     }
146   }
147
148   // done encoding, return number of encoded bytes
149   return *bitstream_len_byte;
150 }
151
152 int16_t ACMG729::EnableDTX() {
153   if (dtx_enabled_) {
154     // DTX already enabled, do nothing
155     return 0;
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) {
159       return -1;
160     }
161     dtx_enabled_ = true;
162     return 0;
163   } else {
164     return -1;
165   }
166 }
167
168 int16_t ACMG729::DisableDTX() {
169   if (!dtx_enabled_) {
170     // DTX already dissabled, do nothing
171     return 0;
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) {
175       return -1;
176     }
177     dtx_enabled_ = false;
178     return 0;
179   } else {
180     // encoder doesn't exists, therefore disabling is harmless
181     return 0;
182   }
183 }
184
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
187   // external instead.
188
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
196       DisableDTX();
197     } else {
198       // Disable external DTX before enabling internal
199       ACMGenericCodec::DisableDTX();
200     }
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
204     // reported
205     if (status == 1) {
206       vad_enabled_ = true;
207       return status;
208     } else if (status < 0) {
209       has_internal_dtx_ = replace_internal_dtx;
210       return -1;
211     }
212   }
213   return 0;
214 }
215
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_;
219   return 0;
220 }
221
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));
226 }
227
228 ACMGenericCodec* ACMG729::CreateInstance(void) {
229   // Function not used
230   return NULL;
231 }
232
233 int16_t ACMG729::InternalCreateEncoder() {
234   // Create encoder memory
235   return WebRtcG729_CreateEnc(&encoder_inst_ptr_);
236 }
237
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;
245   }
246 }
247
248 void ACMG729::InternalDestructEncoderInst(void* ptr_inst) {
249   if (ptr_inst != NULL) {
250     WebRtcG729_FreeEnc(static_cast<G729_encinst_t_*>(ptr_inst));
251   }
252   return;
253 }
254
255 #endif
256
257 }  // namespace acm2
258
259 }  // namespace webrtc