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 int16_t ACMAMR::SetAMREncoderPackingFormat(
     81     ACMAMRPackingFormat /* packing_format */) {
     82   return -1;
     83 }
     84 
     85 ACMAMRPackingFormat ACMAMR::AMREncoderPackingFormat() const {
     86   return AMRUndefined;
     87 }
     88 
     89 int16_t ACMAMR::SetAMRDecoderPackingFormat(
     90     ACMAMRPackingFormat /* packing_format */) {
     91   return -1;
     92 }
     93 
     94 ACMAMRPackingFormat ACMAMR::AMRDecoderPackingFormat() const {
     95   return AMRUndefined;
     96 }
     97 
     98 #else     //===================== Actual Implementation =======================
     99 
    100 #define WEBRTC_AMR_MR475 0
    101 #define WEBRTC_AMR_MR515 1
    102 #define WEBRTC_AMR_MR59 2
    103 #define WEBRTC_AMR_MR67 3
    104 #define WEBRTC_AMR_MR74 4
    105 #define WEBRTC_AMR_MR795 5
    106 #define WEBRTC_AMR_MR102 6
    107 #define WEBRTC_AMR_MR122 7
    108 
    109 ACMAMR::ACMAMR(int16_t codec_id)
    110     : encoder_inst_ptr_(NULL),
    111       encoding_mode_(-1),  // invalid value
    112       encoding_rate_(0) {  // invalid value
    113   codec_id_ = codec_id;
    114   has_internal_dtx_ = true;
    115   encoder_packing_format_ = AMRBandwidthEfficient;
    116   return;
    117 }
    118 
    119 ACMAMR::~ACMAMR() {
    120   if (encoder_inst_ptr_ != NULL) {
    121     WebRtcAmr_FreeEnc(encoder_inst_ptr_);
    122     encoder_inst_ptr_ = NULL;
    123   }
    124   return;
    125 }
    126 
    127 int16_t ACMAMR::InternalEncode(uint8_t* bitstream,
    128                                int16_t* bitstream_len_byte) {
    129   int16_t vad_decision = 1;
    130   // sanity check, if the rate is set correctly. we might skip this
    131   // sanity check. if rate is not set correctly, initialization flag
    132   // should be false and should not be here.
    133   if ((encoding_mode_ < WEBRTC_AMR_MR475) ||
    134       (encoding_mode_ > WEBRTC_AMR_MR122)) {
    135     *bitstream_len_byte = 0;
    136     return -1;
    137   }
    138   *bitstream_len_byte = WebRtcAmr_Encode(encoder_inst_ptr_,
    139                                          &in_audio_[in_audio_ix_read_],
    140                                          frame_len_smpl_,
    141                                          reinterpret_cast<int16_t*>(bitstream),
    142                                          encoding_mode_);
    143 
    144   // Update VAD, if internal DTX is used
    145   if (has_internal_dtx_ && dtx_enabled_) {
    146     if (*bitstream_len_byte <= (7 * frame_len_smpl_ / 160)) {
    147       vad_decision = 0;
    148     }
    149     for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
    150       vad_label_[n] = vad_decision;
    151     }
    152   }
    153   // increment the read index
    154   in_audio_ix_read_ += frame_len_smpl_;
    155   return *bitstream_len_byte;
    156 }
    157 
    158 int16_t ACMAMR::EnableDTX() {
    159   if (dtx_enabled_) {
    160     return 0;
    161   } else if (encoder_exist_) {  // check if encoder exist
    162     // enable DTX
    163     if (WebRtcAmr_EncoderInit(encoder_inst_ptr_, 1) < 0) {
    164       return -1;
    165     }
    166     dtx_enabled_ = true;
    167     return 0;
    168   } else {
    169     return -1;
    170   }
    171 }
    172 
    173 int16_t ACMAMR::DisableDTX() {
    174   if (!dtx_enabled_) {
    175     return 0;
    176   } else if (encoder_exist_) {  // check if encoder exist
    177     // disable DTX
    178     if (WebRtcAmr_EncoderInit(encoder_inst_ptr_, 0) < 0) {
    179       return -1;
    180     }
    181     dtx_enabled_ = false;
    182     return 0;
    183   } else {
    184     // encoder doesn't exists, therefore disabling is harmless
    185     return 0;
    186   }
    187 }
    188 
    189 int16_t ACMAMR::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
    190   int16_t status = SetBitRateSafe((codec_params->codec_inst).rate);
    191   status += (WebRtcAmr_EncoderInit(encoder_inst_ptr_,
    192                                    ((codec_params->enable_dtx) ? 1 : 0)) < 0)
    193                 ? -1
    194                 : 0;
    195   status +=
    196       (WebRtcAmr_EncodeBitmode(encoder_inst_ptr_, encoder_packing_format_) < 0)
    197           ? -1
    198           : 0;
    199   return (status < 0) ? -1 : 0;
    200 }
    201 
    202 ACMGenericCodec* ACMAMR::CreateInstance(void) { return NULL; }
    203 
    204 int16_t ACMAMR::InternalCreateEncoder() {
    205   return WebRtcAmr_CreateEnc(&encoder_inst_ptr_);
    206 }
    207 
    208 void ACMAMR::DestructEncoderSafe() {
    209   if (encoder_inst_ptr_ != NULL) {
    210     WebRtcAmr_FreeEnc(encoder_inst_ptr_);
    211     encoder_inst_ptr_ = NULL;
    212   }
    213   // there is no encoder set the following
    214   encoder_exist_ = false;
    215   encoder_initialized_ = false;
    216   encoding_mode_ = -1;  // invalid value
    217   encoding_rate_ = 0;   // invalid value
    218 }
    219 
    220 int16_t ACMAMR::SetBitRateSafe(const int32_t rate) {
    221   switch (rate) {
    222     case 4750: {
    223       encoding_mode_ = WEBRTC_AMR_MR475;
    224       encoding_rate_ = 4750;
    225       break;
    226     }
    227     case 5150: {
    228       encoding_mode_ = WEBRTC_AMR_MR515;
    229       encoding_rate_ = 5150;
    230       break;
    231     }
    232     case 5900: {
    233       encoding_mode_ = WEBRTC_AMR_MR59;
    234       encoding_rate_ = 5900;
    235       break;
    236     }
    237     case 6700: {
    238       encoding_mode_ = WEBRTC_AMR_MR67;
    239       encoding_rate_ = 6700;
    240       break;
    241     }
    242     case 7400: {
    243       encoding_mode_ = WEBRTC_AMR_MR74;
    244       encoding_rate_ = 7400;
    245       break;
    246     }
    247     case 7950: {
    248       encoding_mode_ = WEBRTC_AMR_MR795;
    249       encoding_rate_ = 7950;
    250       break;
    251     }
    252     case 10200: {
    253       encoding_mode_ = WEBRTC_AMR_MR102;
    254       encoding_rate_ = 10200;
    255       break;
    256     }
    257     case 12200: {
    258       encoding_mode_ = WEBRTC_AMR_MR122;
    259       encoding_rate_ = 12200;
    260       break;
    261     }
    262     default: {
    263       return -1;
    264     }
    265   }
    266   return 0;
    267 }
    268 
    269 int16_t ACMAMR::SetAMREncoderPackingFormat(ACMAMRPackingFormat packing_format) {
    270   if ((packing_format != AMRBandwidthEfficient) &&
    271       (packing_format != AMROctetAlligned) &&
    272       (packing_format != AMRFileStorage)) {
    273     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
    274                  "Invalid AMR Encoder packing-format.");
    275     return -1;
    276   } else {
    277     if (WebRtcAmr_EncodeBitmode(encoder_inst_ptr_, packing_format) < 0) {
    278       return -1;
    279     } else {
    280       encoder_packing_format_ = packing_format;
    281       return 0;
    282     }
    283   }
    284 }
    285 
    286 ACMAMRPackingFormat ACMAMR::AMREncoderPackingFormat() const {
    287   return encoder_packing_format_;
    288 }
    289 
    290 int16_t ACMAMR::SetAMRDecoderPackingFormat(
    291     ACMAMRPackingFormat /* packing_format */) {
    292   // Not implemented.
    293   return -1;
    294 }
    295 
    296 ACMAMRPackingFormat ACMAMR::AMRDecoderPackingFormat() const {
    297   // Not implemented.
    298   return AMRUndefined;
    299 }
    300 
    301 #endif
    302 }  // namespace acm2
    303 
    304 }  // namespace webrtc
    305