Home | History | Annotate | Download | only in acm2
      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_amr.h"
     12 
     13 #ifdef WEBRTC_CODEC_AMR
     14 // NOTE! GSM AMR is not included in the open-source package. The following
     15 // interface file is needed:
     16 #include "webrtc/modules/audio_coding/main/codecs/amr/interface/amr_interface.h"
     17 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
     18 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
     19 #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
     20 #include "webrtc/system_wrappers/interface/trace.h"
     21 
     22 // The API in the header file should match the one below.
     23 //
     24 // int16_t WebRtcAmr_CreateEnc(AMR_encinst_t_** enc_inst);
     25 // int16_t WebRtcAmr_CreateDec(AMR_decinst_t_** dec_inst);
     26 // int16_t WebRtcAmr_FreeEnc(AMR_encinst_t_* enc_inst);
     27 // int16_t WebRtcAmr_FreeDec(AMR_decinst_t_* dec_inst);
     28 // int16_t WebRtcAmr_Encode(AMR_encinst_t_* enc_inst,
     29 //                          int16_t* input,
     30 //                          int16_t len,
     31 //                          int16_t*output,
     32 //                          int16_t mode);
     33 //  int16_t WebRtcAmr_EncoderInit(AMR_encinst_t_* enc_inst,
     34 //                               int16_t dtx_mode);
     35 // int16_t WebRtcAmr_EncodeBitmode(AMR_encinst_t_* enc_inst,
     36 //                                 int format);
     37 // int16_t WebRtcAmr_Decode(AMR_decinst_t_* dec_inst);
     38 // int16_t WebRtcAmr_DecodePlc(AMR_decinst_t_* dec_inst);
     39 // int16_t WebRtcAmr_DecoderInit(AMR_decinst_t_* dec_inst);
     40 // int16_t WebRtcAmr_DecodeBitmode(AMR_decinst_t_* dec_inst,
     41 //                                 int format);
     42 #endif
     43 
     44 namespace webrtc {
     45 
     46 namespace acm2 {
     47 
     48 #ifndef WEBRTC_CODEC_AMR
     49 ACMAMR::ACMAMR(int16_t /* codec_id */)
     50     : encoder_inst_ptr_(NULL),
     51       encoding_mode_(-1),  // Invalid value.
     52       encoding_rate_(0),   // Invalid value.
     53       encoder_packing_format_(AMRBandwidthEfficient) {
     54   return;
     55 }
     56 
     57 ACMAMR::~ACMAMR() { return; }
     58 
     59 int16_t ACMAMR::InternalEncode(uint8_t* /* bitstream */,
     60                                int16_t* /* bitstream_len_byte */) {
     61   return -1;
     62 }
     63 
     64 int16_t ACMAMR::EnableDTX() { return -1; }
     65 
     66 int16_t ACMAMR::DisableDTX() { return -1; }
     67 
     68 int16_t ACMAMR::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
     69   return -1;
     70 }
     71 
     72 ACMGenericCodec* ACMAMR::CreateInstance(void) { return NULL; }
     73 
     74 int16_t ACMAMR::InternalCreateEncoder() { return -1; }
     75 
     76 void ACMAMR::DestructEncoderSafe() { return; }
     77 
     78 int16_t ACMAMR::SetBitRateSafe(const int32_t /* rate */) { return -1; }
     79 
     80 void ACMAMR::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
     81 
     82 int16_t ACMAMR::SetAMREncoderPackingFormat(
     83     ACMAMRPackingFormat /* packing_format */) {
     84   return -1;
     85 }
     86 
     87 ACMAMRPackingFormat ACMAMR::AMREncoderPackingFormat() const {
     88   return AMRUndefined;
     89 }
     90 
     91 int16_t ACMAMR::SetAMRDecoderPackingFormat(
     92     ACMAMRPackingFormat /* packing_format */) {
     93   return -1;
     94 }
     95 
     96 ACMAMRPackingFormat ACMAMR::AMRDecoderPackingFormat() const {
     97   return AMRUndefined;
     98 }
     99 
    100 #else     //===================== Actual Implementation =======================
    101 
    102 #define WEBRTC_AMR_MR475 0
    103 #define WEBRTC_AMR_MR515 1
    104 #define WEBRTC_AMR_MR59 2
    105 #define WEBRTC_AMR_MR67 3
    106 #define WEBRTC_AMR_MR74 4
    107 #define WEBRTC_AMR_MR795 5
    108 #define WEBRTC_AMR_MR102 6
    109 #define WEBRTC_AMR_MR122 7
    110 
    111 ACMAMR::ACMAMR(int16_t codec_id)
    112     : encoder_inst_ptr_(NULL),
    113       encoding_mode_(-1),  // invalid value
    114       encoding_rate_(0) {  // invalid value
    115   codec_id_ = codec_id;
    116   has_internal_dtx_ = true;
    117   encoder_packing_format_ = AMRBandwidthEfficient;
    118   return;
    119 }
    120 
    121 ACMAMR::~ACMAMR() {
    122   if (encoder_inst_ptr_ != NULL) {
    123     WebRtcAmr_FreeEnc(encoder_inst_ptr_);
    124     encoder_inst_ptr_ = NULL;
    125   }
    126   return;
    127 }
    128 
    129 int16_t ACMAMR::InternalEncode(uint8_t* bitstream,
    130                                int16_t* bitstream_len_byte) {
    131   int16_t vad_decision = 1;
    132   // sanity check, if the rate is set correctly. we might skip this
    133   // sanity check. if rate is not set correctly, initialization flag
    134   // should be false and should not be here.
    135   if ((encoding_mode_ < WEBRTC_AMR_MR475) ||
    136       (encoding_mode_ > WEBRTC_AMR_MR122)) {
    137     *bitstream_len_byte = 0;
    138     return -1;
    139   }
    140   *bitstream_len_byte = WebRtcAmr_Encode(encoder_inst_ptr_,
    141                                          &in_audio_[in_audio_ix_read_],
    142                                          frame_len_smpl_,
    143                                          reinterpret_cast<int16_t*>(bitstream),
    144                                          encoding_mode_);
    145 
    146   // Update VAD, if internal DTX is used
    147   if (has_internal_dtx_ && dtx_enabled_) {
    148     if (*bitstream_len_byte <= (7 * frame_len_smpl_ / 160)) {
    149       vad_decision = 0;
    150     }
    151     for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
    152       vad_label_[n] = vad_decision;
    153     }
    154   }
    155   // increment the read index
    156   in_audio_ix_read_ += frame_len_smpl_;
    157   return *bitstream_len_byte;
    158 }
    159 
    160 int16_t ACMAMR::EnableDTX() {
    161   if (dtx_enabled_) {
    162     return 0;
    163   } else if (encoder_exist_) {  // check if encoder exist
    164     // enable DTX
    165     if (WebRtcAmr_EncoderInit(encoder_inst_ptr_, 1) < 0) {
    166       return -1;
    167     }
    168     dtx_enabled_ = true;
    169     return 0;
    170   } else {
    171     return -1;
    172   }
    173 }
    174 
    175 int16_t ACMAMR::DisableDTX() {
    176   if (!dtx_enabled_) {
    177     return 0;
    178   } else if (encoder_exist_) {  // check if encoder exist
    179     // disable DTX
    180     if (WebRtcAmr_EncoderInit(encoder_inst_ptr_, 0) < 0) {
    181       return -1;
    182     }
    183     dtx_enabled_ = false;
    184     return 0;
    185   } else {
    186     // encoder doesn't exists, therefore disabling is harmless
    187     return 0;
    188   }
    189 }
    190 
    191 int16_t ACMAMR::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
    192   int16_t status = SetBitRateSafe((codec_params->codec_inst).rate);
    193   status += (WebRtcAmr_EncoderInit(encoder_inst_ptr_,
    194                                    ((codec_params->enable_dtx) ? 1 : 0)) < 0)
    195                 ? -1
    196                 : 0;
    197   status +=
    198       (WebRtcAmr_EncodeBitmode(encoder_inst_ptr_, encoder_packing_format_) < 0)
    199           ? -1
    200           : 0;
    201   return (status < 0) ? -1 : 0;
    202 }
    203 
    204 ACMGenericCodec* ACMAMR::CreateInstance(void) { return NULL; }
    205 
    206 int16_t ACMAMR::InternalCreateEncoder() {
    207   return WebRtcAmr_CreateEnc(&encoder_inst_ptr_);
    208 }
    209 
    210 void ACMAMR::DestructEncoderSafe() {
    211   if (encoder_inst_ptr_ != NULL) {
    212     WebRtcAmr_FreeEnc(encoder_inst_ptr_);
    213     encoder_inst_ptr_ = NULL;
    214   }
    215   // there is no encoder set the following
    216   encoder_exist_ = false;
    217   encoder_initialized_ = false;
    218   encoding_mode_ = -1;  // invalid value
    219   encoding_rate_ = 0;   // invalid value
    220 }
    221 
    222 int16_t ACMAMR::SetBitRateSafe(const int32_t rate) {
    223   switch (rate) {
    224     case 4750: {
    225       encoding_mode_ = WEBRTC_AMR_MR475;
    226       encoding_rate_ = 4750;
    227       break;
    228     }
    229     case 5150: {
    230       encoding_mode_ = WEBRTC_AMR_MR515;
    231       encoding_rate_ = 5150;
    232       break;
    233     }
    234     case 5900: {
    235       encoding_mode_ = WEBRTC_AMR_MR59;
    236       encoding_rate_ = 5900;
    237       break;
    238     }
    239     case 6700: {
    240       encoding_mode_ = WEBRTC_AMR_MR67;
    241       encoding_rate_ = 6700;
    242       break;
    243     }
    244     case 7400: {
    245       encoding_mode_ = WEBRTC_AMR_MR74;
    246       encoding_rate_ = 7400;
    247       break;
    248     }
    249     case 7950: {
    250       encoding_mode_ = WEBRTC_AMR_MR795;
    251       encoding_rate_ = 7950;
    252       break;
    253     }
    254     case 10200: {
    255       encoding_mode_ = WEBRTC_AMR_MR102;
    256       encoding_rate_ = 10200;
    257       break;
    258     }
    259     case 12200: {
    260       encoding_mode_ = WEBRTC_AMR_MR122;
    261       encoding_rate_ = 12200;
    262       break;
    263     }
    264     default: {
    265       return -1;
    266     }
    267   }
    268   return 0;
    269 }
    270 
    271 void ACMAMR::InternalDestructEncoderInst(void* ptr_inst) {
    272   // Free the memory where ptr_inst is pointing to
    273   if (ptr_inst != NULL) {
    274     WebRtcAmr_FreeEnc(static_cast<AMR_encinst_t_*>(ptr_inst));
    275   }
    276   return;
    277 }
    278 
    279 int16_t ACMAMR::SetAMREncoderPackingFormat(ACMAMRPackingFormat packing_format) {
    280   if ((packing_format != AMRBandwidthEfficient) &&
    281       (packing_format != AMROctetAlligned) &&
    282       (packing_format != AMRFileStorage)) {
    283     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
    284                  "Invalid AMR Encoder packing-format.");
    285     return -1;
    286   } else {
    287     if (WebRtcAmr_EncodeBitmode(encoder_inst_ptr_, packing_format) < 0) {
    288       return -1;
    289     } else {
    290       encoder_packing_format_ = packing_format;
    291       return 0;
    292     }
    293   }
    294 }
    295 
    296 ACMAMRPackingFormat ACMAMR::AMREncoderPackingFormat() const {
    297   return encoder_packing_format_;
    298 }
    299 
    300 int16_t ACMAMR::SetAMRDecoderPackingFormat(
    301     ACMAMRPackingFormat /* packing_format */) {
    302   // Not implemented.
    303   return -1;
    304 }
    305 
    306 ACMAMRPackingFormat ACMAMR::AMRDecoderPackingFormat() const {
    307   // Not implemented.
    308   return AMRUndefined;
    309 }
    310 
    311 #endif
    312 }  // namespace acm2
    313 
    314 }  // namespace webrtc
    315