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_g722.h"
     12 
     13 #ifdef WEBRTC_CODEC_G722
     14 #include "webrtc/modules/audio_coding/codecs/g722/include/g722_interface.h"
     15 #include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
     16 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
     17 #include "webrtc/system_wrappers/interface/trace.h"
     18 #endif
     19 
     20 namespace webrtc {
     21 
     22 namespace acm2 {
     23 
     24 #ifndef WEBRTC_CODEC_G722
     25 
     26 ACMG722::ACMG722(int16_t /* codec_id */)
     27     : ptr_enc_str_(NULL),
     28       encoder_inst_ptr_(NULL),
     29       encoder_inst_ptr_right_(NULL) {}
     30 
     31 ACMG722::~ACMG722() {}
     32 
     33 int32_t ACMG722::Add10MsDataSafe(const uint32_t /* timestamp */,
     34                                  const int16_t* /* data */,
     35                                  const uint16_t /* length_smpl */,
     36                                  const uint8_t /* audio_channel */) {
     37   return -1;
     38 }
     39 
     40 int16_t ACMG722::InternalEncode(uint8_t* /* bitstream */,
     41                                 int16_t* /* bitstream_len_byte */) {
     42   return -1;
     43 }
     44 
     45 int16_t ACMG722::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
     46   return -1;
     47 }
     48 
     49 ACMGenericCodec* ACMG722::CreateInstance(void) { return NULL; }
     50 
     51 int16_t ACMG722::InternalCreateEncoder() { return -1; }
     52 
     53 void ACMG722::DestructEncoderSafe() { return; }
     54 
     55 #else     //===================== Actual Implementation =======================
     56 
     57 // Encoder and decoder memory
     58 struct ACMG722EncStr {
     59   G722EncInst* inst;  // instance for left channel in case of stereo
     60   G722EncInst* inst_right;  // instance for right channel in case of stereo
     61 };
     62 struct ACMG722DecStr {
     63   G722DecInst* inst;  // instance for left channel in case of stereo
     64   G722DecInst* inst_right;  // instance for right channel in case of stereo
     65 };
     66 
     67 ACMG722::ACMG722(int16_t codec_id)
     68     : encoder_inst_ptr_(NULL), encoder_inst_ptr_right_(NULL) {
     69   ptr_enc_str_ = new ACMG722EncStr;
     70   if (ptr_enc_str_ != NULL) {
     71     ptr_enc_str_->inst = NULL;
     72     ptr_enc_str_->inst_right = NULL;
     73   }
     74   codec_id_ = codec_id;
     75   return;
     76 }
     77 
     78 ACMG722::~ACMG722() {
     79   // Encoder
     80   if (ptr_enc_str_ != NULL) {
     81     if (ptr_enc_str_->inst != NULL) {
     82       WebRtcG722_FreeEncoder(ptr_enc_str_->inst);
     83       ptr_enc_str_->inst = NULL;
     84     }
     85     if (ptr_enc_str_->inst_right != NULL) {
     86       WebRtcG722_FreeEncoder(ptr_enc_str_->inst_right);
     87       ptr_enc_str_->inst_right = NULL;
     88     }
     89     delete ptr_enc_str_;
     90     ptr_enc_str_ = NULL;
     91   }
     92   return;
     93 }
     94 
     95 int32_t ACMG722::Add10MsDataSafe(const uint32_t timestamp,
     96                                  const int16_t* data,
     97                                  const uint16_t length_smpl,
     98                                  const uint8_t audio_channel) {
     99   return ACMGenericCodec::Add10MsDataSafe(
    100       (timestamp >> 1), data, length_smpl, audio_channel);
    101 }
    102 
    103 int16_t ACMG722::InternalEncode(uint8_t* bitstream,
    104                                 int16_t* bitstream_len_byte) {
    105   // If stereo, split input signal in left and right channel before encoding
    106   if (num_channels_ == 2) {
    107     int16_t left_channel[960];
    108     int16_t right_channel[960];
    109     uint8_t out_left[480];
    110     uint8_t out_right[480];
    111     int16_t len_in_bytes;
    112     for (int i = 0, j = 0; i < frame_len_smpl_ * 2; i += 2, j++) {
    113       left_channel[j] = in_audio_[in_audio_ix_read_ + i];
    114       right_channel[j] = in_audio_[in_audio_ix_read_ + i + 1];
    115     }
    116     len_in_bytes = WebRtcG722_Encode(
    117         encoder_inst_ptr_, left_channel, frame_len_smpl_,
    118         reinterpret_cast<int16_t*>(out_left));
    119     len_in_bytes += WebRtcG722_Encode(encoder_inst_ptr_right_,
    120                                       right_channel,
    121                                       frame_len_smpl_,
    122                                       reinterpret_cast<int16_t*>(out_right));
    123     *bitstream_len_byte = len_in_bytes;
    124 
    125     // Interleave the 4 bits per sample from left and right channel
    126     for (int i = 0, j = 0; i < len_in_bytes; i += 2, j++) {
    127       bitstream[i] = (out_left[j] & 0xF0) + (out_right[j] >> 4);
    128       bitstream[i + 1] = ((out_left[j] & 0x0F) << 4) + (out_right[j] & 0x0F);
    129     }
    130   } else {
    131     *bitstream_len_byte = WebRtcG722_Encode(
    132         encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], frame_len_smpl_,
    133         reinterpret_cast<int16_t*>(bitstream));
    134   }
    135 
    136   // increment the read index this tell the caller how far
    137   // we have gone forward in reading the audio buffer
    138   in_audio_ix_read_ += frame_len_smpl_ * num_channels_;
    139   return *bitstream_len_byte;
    140 }
    141 
    142 int16_t ACMG722::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
    143   if (codec_params->codec_inst.channels == 2) {
    144     // Create codec struct for right channel
    145     if (ptr_enc_str_->inst_right == NULL) {
    146       WebRtcG722_CreateEncoder(&ptr_enc_str_->inst_right);
    147       if (ptr_enc_str_->inst_right == NULL) {
    148         return -1;
    149       }
    150     }
    151     encoder_inst_ptr_right_ = ptr_enc_str_->inst_right;
    152     if (WebRtcG722_EncoderInit(encoder_inst_ptr_right_) < 0) {
    153       return -1;
    154     }
    155   }
    156 
    157   return WebRtcG722_EncoderInit(encoder_inst_ptr_);
    158 }
    159 
    160 ACMGenericCodec* ACMG722::CreateInstance(void) { return NULL; }
    161 
    162 int16_t ACMG722::InternalCreateEncoder() {
    163   if (ptr_enc_str_ == NULL) {
    164     // this structure must be created at the costructor
    165     // if it is still NULL then there is a probelm and
    166     // we dont continue
    167     return -1;
    168   }
    169   WebRtcG722_CreateEncoder(&ptr_enc_str_->inst);
    170   if (ptr_enc_str_->inst == NULL) {
    171     return -1;
    172   }
    173   encoder_inst_ptr_ = ptr_enc_str_->inst;
    174   return 0;
    175 }
    176 
    177 void ACMG722::DestructEncoderSafe() {
    178   if (ptr_enc_str_ != NULL) {
    179     if (ptr_enc_str_->inst != NULL) {
    180       WebRtcG722_FreeEncoder(ptr_enc_str_->inst);
    181       ptr_enc_str_->inst = NULL;
    182     }
    183   }
    184   encoder_exist_ = false;
    185   encoder_initialized_ = false;
    186 }
    187 
    188 #endif
    189 
    190 }  // namespace acm2
    191 
    192 }  // namespace webrtc
    193