andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 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 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 11 | #include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h" |
| 12 | |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 13 | #include <assert.h> |
| 14 | #include <string.h> |
| 15 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 16 | #include "webrtc/common_audio/vad/include/webrtc_vad.h" |
| 17 | #include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h" |
| 18 | #include "webrtc/modules/audio_coding/main/source/acm_codec_database.h" |
stefan@webrtc.org | ec09fcb | 2013-09-18 12:34:05 | [diff] [blame^] | 19 | #include "webrtc/modules/audio_coding/main/source/acm_common_defs.h" |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 20 | #include "webrtc/modules/audio_coding/main/source/acm_neteq.h" |
| 21 | #include "webrtc/system_wrappers/interface/trace.h" |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 22 | |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 23 | namespace webrtc { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 24 | |
turaj@webrtc.org | ed0b4fb | 2013-09-13 23:06:59 | [diff] [blame] | 25 | namespace acm1 { |
| 26 | |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 27 | // Enum for CNG |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 28 | enum { |
| 29 | kMaxPLCParamsCNG = WEBRTC_CNG_MAX_LPC_ORDER, |
| 30 | kNewCNGNumPLCParams = 8 |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 31 | }; |
| 32 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 33 | // Interval for sending new CNG parameters (SID frames) is 100 msec. |
| 34 | enum { |
turaj@webrtc.org | 1952f25 | 2012-12-03 22:13:31 | [diff] [blame] | 35 | kCngSidIntervalMsec = 100 |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 36 | }; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 37 | |
| 38 | // We set some of the variables to invalid values as a check point |
| 39 | // if a proper initialization has happened. Another approach is |
| 40 | // to initialize to a default codec that we are sure is always included. |
| 41 | ACMGenericCodec::ACMGenericCodec() |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 42 | : in_audio_ix_write_(0), |
| 43 | in_audio_ix_read_(0), |
| 44 | in_timestamp_ix_write_(0), |
| 45 | in_audio_(NULL), |
| 46 | in_timestamp_(NULL), |
| 47 | frame_len_smpl_(-1), // invalid value |
| 48 | num_channels_(1), |
| 49 | codec_id_(-1), // invalid value |
| 50 | num_missed_samples_(0), |
| 51 | encoder_exist_(false), |
| 52 | decoder_exist_(false), |
| 53 | encoder_initialized_(false), |
| 54 | decoder_initialized_(false), |
| 55 | registered_in_neteq_(false), |
| 56 | has_internal_dtx_(false), |
| 57 | ptr_vad_inst_(NULL), |
| 58 | vad_enabled_(false), |
| 59 | vad_mode_(VADNormal), |
| 60 | dtx_enabled_(false), |
| 61 | ptr_dtx_inst_(NULL), |
| 62 | num_lpc_params_(kNewCNGNumPLCParams), |
| 63 | sent_cn_previous_(false), |
| 64 | is_master_(true), |
| 65 | prev_frame_cng_(0), |
| 66 | neteq_decode_lock_(NULL), |
| 67 | codec_wrapper_lock_(*RWLockWrapper::CreateRWLock()), |
| 68 | last_encoded_timestamp_(0), |
| 69 | last_timestamp_(0xD87F3F9F), |
| 70 | is_audio_buff_fresh_(true), |
| 71 | unique_id_(0) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 72 | // Initialize VAD vector. |
| 73 | for (int i = 0; i < MAX_FRAME_SIZE_10MSEC; i++) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 74 | vad_label_[i] = 0; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 75 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 76 | // Nullify memory for encoder and decoder, and set payload type to an |
| 77 | // invalid value. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 78 | memset(&encoder_params_, 0, sizeof(WebRtcACMCodecParams)); |
| 79 | encoder_params_.codec_inst.pltype = -1; |
| 80 | memset(&decoder_params_, 0, sizeof(WebRtcACMCodecParams)); |
| 81 | decoder_params_.codec_inst.pltype = -1; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 82 | } |
| 83 | |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 84 | ACMGenericCodec::~ACMGenericCodec() { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 85 | // Check all the members which are pointers, and if they are not NULL |
| 86 | // delete/free them. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 87 | if (ptr_vad_inst_ != NULL) { |
| 88 | WebRtcVad_Free(ptr_vad_inst_); |
| 89 | ptr_vad_inst_ = NULL; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 90 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 91 | if (in_audio_ != NULL) { |
| 92 | delete[] in_audio_; |
| 93 | in_audio_ = NULL; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 94 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 95 | if (in_timestamp_ != NULL) { |
| 96 | delete[] in_timestamp_; |
| 97 | in_timestamp_ = NULL; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 98 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 99 | if (ptr_dtx_inst_ != NULL) { |
| 100 | WebRtcCng_FreeEnc(ptr_dtx_inst_); |
| 101 | ptr_dtx_inst_ = NULL; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 102 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 103 | delete &codec_wrapper_lock_; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 104 | } |
| 105 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 106 | int32_t ACMGenericCodec::Add10MsData(const uint32_t timestamp, |
| 107 | const int16_t* data, |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 108 | const uint16_t length_smpl, |
| 109 | const uint8_t audio_channel) { |
| 110 | WriteLockScoped wl(codec_wrapper_lock_); |
| 111 | return Add10MsDataSafe(timestamp, data, length_smpl, audio_channel); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 112 | } |
| 113 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 114 | int32_t ACMGenericCodec::Add10MsDataSafe(const uint32_t timestamp, |
| 115 | const int16_t* data, |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 116 | const uint16_t length_smpl, |
| 117 | const uint8_t audio_channel) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 118 | // The codec expects to get data in correct sampling rate. Get the sampling |
| 119 | // frequency of the codec. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 120 | uint16_t plfreq_hz; |
| 121 | if (EncoderSampFreq(plfreq_hz) < 0) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 122 | return -1; |
| 123 | } |
| 124 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 125 | // Sanity check to make sure the length of the input corresponds to 10 ms. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 126 | if ((plfreq_hz / 100) != length_smpl) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 127 | // This is not 10 ms of audio, given the sampling frequency of the codec. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 128 | return -1; |
| 129 | } |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 130 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 131 | if (last_timestamp_ == timestamp) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 132 | // Same timestamp as the last time, overwrite. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 133 | if ((in_audio_ix_write_ >= length_smpl * audio_channel) && |
| 134 | (in_timestamp_ix_write_ > 0)) { |
| 135 | in_audio_ix_write_ -= length_smpl * audio_channel; |
| 136 | in_timestamp_ix_write_--; |
| 137 | WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_, |
| 138 | "Adding 10ms with previous timestamp, overwriting the " |
| 139 | "previous 10ms"); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 140 | } else { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 141 | WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 142 | "Adding 10ms with previous timestamp, this will sound bad"); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 143 | } |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 144 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 145 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 146 | last_timestamp_ = timestamp; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 147 | |
turaj@webrtc.org | 1952f25 | 2012-12-03 22:13:31 | [diff] [blame] | 148 | // If the data exceeds the buffer size, we throw away the oldest data and |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 149 | // add the newly received 10 msec at the end. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 150 | if ((in_audio_ix_write_ + length_smpl * audio_channel) > |
| 151 | AUDIO_BUFFER_SIZE_W16) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 152 | // Get the number of samples to be overwritten. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 153 | int16_t missed_samples = in_audio_ix_write_ + length_smpl * audio_channel - |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 154 | AUDIO_BUFFER_SIZE_W16; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 155 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 156 | // Move the data (overwrite the old data). |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 157 | memmove(in_audio_, in_audio_ + missed_samples, |
| 158 | (AUDIO_BUFFER_SIZE_W16 - length_smpl * audio_channel) * |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 159 | sizeof(int16_t)); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 160 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 161 | // Copy the new data. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 162 | memcpy(in_audio_ + (AUDIO_BUFFER_SIZE_W16 - length_smpl * audio_channel), |
| 163 | data, length_smpl * audio_channel * sizeof(int16_t)); |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 164 | |
| 165 | // Get the number of 10 ms blocks which are overwritten. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 166 | int16_t missed_10ms_blocks =static_cast<int16_t>( |
| 167 | (missed_samples / audio_channel * 100) / plfreq_hz); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 168 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 169 | // Move the timestamps. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 170 | memmove(in_timestamp_, in_timestamp_ + missed_10ms_blocks, |
| 171 | (in_timestamp_ix_write_ - missed_10ms_blocks) * sizeof(uint32_t)); |
| 172 | in_timestamp_ix_write_ -= missed_10ms_blocks; |
| 173 | in_timestamp_[in_timestamp_ix_write_] = timestamp; |
| 174 | in_timestamp_ix_write_++; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 175 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 176 | // Buffer is full. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 177 | in_audio_ix_write_ = AUDIO_BUFFER_SIZE_W16; |
| 178 | IncreaseNoMissedSamples(missed_samples); |
| 179 | is_audio_buff_fresh_ = false; |
| 180 | return -missed_samples; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 181 | } |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 182 | |
| 183 | // Store the input data in our data buffer. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 184 | memcpy(in_audio_ + in_audio_ix_write_, data, |
| 185 | length_smpl * audio_channel * sizeof(int16_t)); |
| 186 | in_audio_ix_write_ += length_smpl * audio_channel; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 187 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 188 | assert(in_timestamp_ix_write_ < TIMESTAMP_BUFFER_SIZE_W32); |
| 189 | assert(in_timestamp_ix_write_ >= 0); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 190 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 191 | in_timestamp_[in_timestamp_ix_write_] = timestamp; |
| 192 | in_timestamp_ix_write_++; |
| 193 | is_audio_buff_fresh_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 194 | return 0; |
| 195 | } |
| 196 | |
turaj@webrtc.org | 1952f25 | 2012-12-03 22:13:31 | [diff] [blame] | 197 | bool ACMGenericCodec::HasFrameToEncode() const { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 198 | ReadLockScoped lockCodec(codec_wrapper_lock_); |
| 199 | if (in_audio_ix_write_ < frame_len_smpl_ * num_channels_) |
turaj@webrtc.org | 1952f25 | 2012-12-03 22:13:31 | [diff] [blame] | 200 | return false; |
| 201 | return true; |
| 202 | } |
| 203 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 204 | int16_t ACMGenericCodec::Encode(uint8_t* bitstream, |
| 205 | int16_t* bitstream_len_byte, |
| 206 | uint32_t* timestamp, |
| 207 | WebRtcACMEncodingType* encoding_type) { |
turaj@webrtc.org | 1952f25 | 2012-12-03 22:13:31 | [diff] [blame] | 208 | if (!HasFrameToEncode()) { |
| 209 | // There is not enough audio |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 210 | *timestamp = 0; |
| 211 | *bitstream_len_byte = 0; |
turaj@webrtc.org | 1952f25 | 2012-12-03 22:13:31 | [diff] [blame] | 212 | // Doesn't really matter what this parameter set to |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 213 | *encoding_type = kNoEncoding; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 214 | return 0; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 215 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 216 | WriteLockScoped lockCodec(codec_wrapper_lock_); |
| 217 | ReadLockScoped lockNetEq(*neteq_decode_lock_); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 218 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 219 | // Not all codecs accept the whole frame to be pushed into encoder at once. |
| 220 | // Some codecs needs to be feed with a specific number of samples different |
| 221 | // from the frame size. If this is the case, |myBasicCodingBlockSmpl| will |
| 222 | // report a number different from 0, and we will loop over calls to encoder |
| 223 | // further down, until we have encode a complete frame. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 224 | const int16_t my_basic_coding_block_smpl = |
| 225 | ACMCodecDB::BasicCodingBlock(codec_id_); |
| 226 | if (my_basic_coding_block_smpl < 0 || !encoder_initialized_ || |
| 227 | !encoder_exist_) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 228 | // This should not happen, but in case it does, report no encoding done. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 229 | *timestamp = 0; |
| 230 | *bitstream_len_byte = 0; |
| 231 | *encoding_type = kNoEncoding; |
| 232 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 233 | "EncodeSafe: error, basic coding sample block is negative"); |
| 234 | return -1; |
| 235 | } |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 236 | // This makes the internal encoder read from the beginning of the buffer. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 237 | in_audio_ix_read_ = 0; |
| 238 | *timestamp = in_timestamp_[0]; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 239 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 240 | // Process the audio through VAD. The function will set |_vad_labels|. |
| 241 | // If VAD is disabled all entries in |_vad_labels| are set to ONE (active). |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 242 | int16_t status = 0; |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 243 | int16_t dtx_processed_samples = 0; |
| 244 | status = ProcessFrameVADDTX(bitstream, bitstream_len_byte, |
| 245 | &dtx_processed_samples); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 246 | if (status < 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 247 | *timestamp = 0; |
| 248 | *bitstream_len_byte = 0; |
| 249 | *encoding_type = kNoEncoding; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 250 | } else { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 251 | if (dtx_processed_samples > 0) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 252 | // Dtx have processed some samples, and even if a bit-stream is generated |
| 253 | // we should not do any encoding (normally there won't be enough data). |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 254 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 255 | // Setting the following makes sure that the move of audio data and |
| 256 | // timestamps done correctly. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 257 | in_audio_ix_read_ = dtx_processed_samples; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 258 | // This will let the owner of ACMGenericCodec to know that the |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 259 | // generated bit-stream is DTX to use correct payload type. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 260 | uint16_t samp_freq_hz; |
| 261 | EncoderSampFreq(samp_freq_hz); |
| 262 | if (samp_freq_hz == 8000) { |
| 263 | *encoding_type = kPassiveDTXNB; |
| 264 | } else if (samp_freq_hz == 16000) { |
| 265 | *encoding_type = kPassiveDTXWB; |
| 266 | } else if (samp_freq_hz == 32000) { |
| 267 | *encoding_type = kPassiveDTXSWB; |
| 268 | } else if (samp_freq_hz == 48000) { |
| 269 | *encoding_type = kPassiveDTXFB; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 270 | } else { |
| 271 | status = -1; |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 272 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 273 | "EncodeSafe: Wrong sampling frequency for DTX."); |
| 274 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 275 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 276 | // Transport empty frame if we have an empty bitstream. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 277 | if ((*bitstream_len_byte == 0) && |
| 278 | (sent_cn_previous_ || |
| 279 | ((in_audio_ix_write_ - in_audio_ix_read_) <= 0))) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 280 | // Makes sure we transmit an empty frame. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 281 | *bitstream_len_byte = 1; |
| 282 | *encoding_type = kNoEncoding; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 283 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 284 | sent_cn_previous_ = true; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 285 | } else { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 286 | // We should encode the audio frame. Either VAD and/or DTX is off, or the |
| 287 | // audio was considered "active". |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 288 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 289 | sent_cn_previous_ = false; |
| 290 | if (my_basic_coding_block_smpl == 0) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 291 | // This codec can handle all allowed frame sizes as basic coding block. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 292 | status = InternalEncode(bitstream, bitstream_len_byte); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 293 | if (status < 0) { |
| 294 | // TODO(tlegrand): Maybe reseting the encoder to be fresh for the next |
| 295 | // frame. |
| 296 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 297 | unique_id_, "EncodeSafe: error in internal_encode"); |
| 298 | *bitstream_len_byte = 0; |
| 299 | *encoding_type = kNoEncoding; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 300 | } |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 301 | } else { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 302 | // A basic-coding-block for this codec is defined so we loop over the |
| 303 | // audio with the steps of the basic-coding-block. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 304 | int16_t tmp_bitstream_len_byte; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 305 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 306 | // Reset the variables which will be incremented in the loop. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 307 | *bitstream_len_byte = 0; |
tina.legrand@webrtc.org | cbb535a | 2013-07-03 09:25:34 | [diff] [blame] | 308 | do { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 309 | status = InternalEncode(&bitstream[*bitstream_len_byte], |
| 310 | &tmp_bitstream_len_byte); |
| 311 | *bitstream_len_byte += tmp_bitstream_len_byte; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 312 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 313 | // Guard Against errors and too large payloads. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 314 | if ((status < 0) || (*bitstream_len_byte > MAX_PAYLOAD_SIZE_BYTE)) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 315 | // Error has happened, and even if we are in the middle of a full |
| 316 | // frame we have to exit. Before exiting, whatever bits are in the |
| 317 | // buffer are probably corrupted, so we ignore them. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 318 | *bitstream_len_byte = 0; |
| 319 | *encoding_type = kNoEncoding; |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 320 | // We might have come here because of the second condition. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 321 | status = -1; |
| 322 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 323 | unique_id_, "EncodeSafe: error in InternalEncode"); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 324 | // break from the loop |
| 325 | break; |
| 326 | } |
tina.legrand@webrtc.org | cbb535a | 2013-07-03 09:25:34 | [diff] [blame] | 327 | } while (in_audio_ix_read_ < frame_len_smpl_ * num_channels_); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 328 | } |
| 329 | if (status >= 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 330 | *encoding_type = (vad_label_[0] == 1) ? kActiveNormalEncoded : |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 331 | kPassiveNormalEncoded; |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 332 | // Transport empty frame if we have an empty bitstream. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 333 | if ((*bitstream_len_byte == 0) && |
| 334 | ((in_audio_ix_write_ - in_audio_ix_read_) <= 0)) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 335 | // Makes sure we transmit an empty frame. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 336 | *bitstream_len_byte = 1; |
| 337 | *encoding_type = kNoEncoding; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 338 | } |
| 339 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 340 | } |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 341 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 342 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 343 | // Move the timestamp buffer according to the number of 10 ms blocks |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 344 | // which are read. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 345 | uint16_t samp_freq_hz; |
| 346 | EncoderSampFreq(samp_freq_hz); |
| 347 | int16_t num_10ms_blocks = static_cast<int16_t>( |
| 348 | (in_audio_ix_read_ / num_channels_ * 100) / samp_freq_hz); |
| 349 | if (in_timestamp_ix_write_ > num_10ms_blocks) { |
| 350 | memmove(in_timestamp_, in_timestamp_ + num_10ms_blocks, |
| 351 | (in_timestamp_ix_write_ - num_10ms_blocks) * sizeof(int32_t)); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 352 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 353 | in_timestamp_ix_write_ -= num_10ms_blocks; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 354 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 355 | // Remove encoded audio and move next audio to be encoded to the beginning |
| 356 | // of the buffer. Accordingly, adjust the read and write indices. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 357 | if (in_audio_ix_read_ < in_audio_ix_write_) { |
| 358 | memmove(in_audio_, &in_audio_[in_audio_ix_read_], |
| 359 | (in_audio_ix_write_ - in_audio_ix_read_) * sizeof(int16_t)); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 360 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 361 | in_audio_ix_write_ -= in_audio_ix_read_; |
| 362 | in_audio_ix_read_ = 0; |
| 363 | last_encoded_timestamp_ = *timestamp; |
| 364 | return (status < 0) ? (-1) : (*bitstream_len_byte); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 365 | } |
| 366 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 367 | int16_t ACMGenericCodec::Decode(uint8_t* bitstream, |
| 368 | int16_t bitstream_len_byte, |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 369 | int16_t* audio, |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 370 | int16_t* audio_samples, |
| 371 | int8_t* speech_type) { |
| 372 | WriteLockScoped wl(codec_wrapper_lock_); |
| 373 | return DecodeSafe(bitstream, bitstream_len_byte, audio, audio_samples, |
| 374 | speech_type); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 375 | } |
| 376 | |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 377 | bool ACMGenericCodec::EncoderInitialized() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 378 | ReadLockScoped rl(codec_wrapper_lock_); |
| 379 | return encoder_initialized_; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 380 | } |
| 381 | |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 382 | bool ACMGenericCodec::DecoderInitialized() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 383 | ReadLockScoped rl(codec_wrapper_lock_); |
| 384 | return decoder_initialized_; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 385 | } |
| 386 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 387 | int32_t ACMGenericCodec::RegisterInNetEq(ACMNetEQ* neteq, |
| 388 | const CodecInst& codec_inst) { |
| 389 | WebRtcNetEQ_CodecDef codec_def; |
| 390 | WriteLockScoped wl(codec_wrapper_lock_); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 391 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 392 | if (CodecDef(codec_def, codec_inst) < 0) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 393 | // Failed to register the decoder. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 394 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 395 | "RegisterInNetEq: error, failed to register"); |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 396 | registered_in_neteq_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 397 | return -1; |
| 398 | } else { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 399 | if (neteq->AddCodec(&codec_def, is_master_) < 0) { |
| 400 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 401 | "RegisterInNetEq: error, failed to add codec"); |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 402 | registered_in_neteq_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 403 | return -1; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 404 | } |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 405 | // Succeeded registering the decoder. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 406 | registered_in_neteq_ = true; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 407 | return 0; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 408 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 409 | } |
| 410 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 411 | int16_t ACMGenericCodec::EncoderParams(WebRtcACMCodecParams* enc_params) { |
| 412 | ReadLockScoped rl(codec_wrapper_lock_); |
| 413 | return EncoderParamsSafe(enc_params); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 414 | } |
| 415 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 416 | int16_t ACMGenericCodec::EncoderParamsSafe(WebRtcACMCodecParams* enc_params) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 417 | // Codec parameters are valid only if the encoder is initialized. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 418 | if (encoder_initialized_) { |
| 419 | int32_t current_rate; |
| 420 | memcpy(enc_params, &encoder_params_, sizeof(WebRtcACMCodecParams)); |
| 421 | current_rate = enc_params->codec_inst.rate; |
| 422 | CurrentRate(current_rate); |
| 423 | enc_params->codec_inst.rate = current_rate; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 424 | return 0; |
| 425 | } else { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 426 | enc_params->codec_inst.plname[0] = '\0'; |
| 427 | enc_params->codec_inst.pltype = -1; |
| 428 | enc_params->codec_inst.pacsize = 0; |
| 429 | enc_params->codec_inst.rate = 0; |
| 430 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 431 | "EncoderParamsSafe: error, encoder not initialized"); |
| 432 | return -1; |
| 433 | } |
| 434 | } |
| 435 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 436 | bool ACMGenericCodec::DecoderParams(WebRtcACMCodecParams* dec_params, |
| 437 | const uint8_t payload_type) { |
| 438 | ReadLockScoped rl(codec_wrapper_lock_); |
| 439 | return DecoderParamsSafe(dec_params, payload_type); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 440 | } |
| 441 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 442 | bool ACMGenericCodec::DecoderParamsSafe(WebRtcACMCodecParams* dec_params, |
| 443 | const uint8_t payload_type) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 444 | // Decoder parameters are valid only if decoder is initialized. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 445 | if (decoder_initialized_) { |
| 446 | if (payload_type == decoder_params_.codec_inst.pltype) { |
| 447 | memcpy(dec_params, &decoder_params_, sizeof(WebRtcACMCodecParams)); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 448 | return true; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 449 | } |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 450 | } |
| 451 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 452 | dec_params->codec_inst.plname[0] = '\0'; |
| 453 | dec_params->codec_inst.pltype = -1; |
| 454 | dec_params->codec_inst.pacsize = 0; |
| 455 | dec_params->codec_inst.rate = 0; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 456 | return false; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 457 | } |
| 458 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 459 | int16_t ACMGenericCodec::ResetEncoder() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 460 | WriteLockScoped lockCodec(codec_wrapper_lock_); |
| 461 | ReadLockScoped lockNetEq(*neteq_decode_lock_); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 462 | return ResetEncoderSafe(); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 463 | } |
| 464 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 465 | int16_t ACMGenericCodec::ResetEncoderSafe() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 466 | if (!encoder_exist_ || !encoder_initialized_) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 467 | // We don't reset if encoder doesn't exists or isn't initialized yet. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 468 | return 0; |
| 469 | } |
| 470 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 471 | in_audio_ix_write_ = 0; |
| 472 | in_audio_ix_read_ = 0; |
| 473 | in_timestamp_ix_write_ = 0; |
| 474 | num_missed_samples_ = 0; |
| 475 | is_audio_buff_fresh_ = true; |
| 476 | memset(in_audio_, 0, AUDIO_BUFFER_SIZE_W16 * sizeof(int16_t)); |
| 477 | memset(in_timestamp_, 0, TIMESTAMP_BUFFER_SIZE_W32 * sizeof(int32_t)); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 478 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 479 | // Store DTX/VAD parameters. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 480 | bool enable_vad = vad_enabled_; |
| 481 | bool enable_dtx = dtx_enabled_; |
| 482 | ACMVADMode mode = vad_mode_; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 483 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 484 | // Reset the encoder. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 485 | if (InternalResetEncoder() < 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 486 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 487 | "ResetEncoderSafe: error in reset encoder"); |
| 488 | return -1; |
| 489 | } |
| 490 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 491 | // Disable DTX & VAD to delete the states and have a fresh start. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 492 | DisableDTX(); |
| 493 | DisableVAD(); |
| 494 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 495 | // Set DTX/VAD. |
tina.legrand@webrtc.org | 584b688 | 2013-08-27 07:33:51 | [diff] [blame] | 496 | int status = SetVADSafe(&enable_dtx, &enable_vad, &mode); |
| 497 | vad_enabled_ = enable_dtx; |
| 498 | dtx_enabled_ = enable_vad; |
| 499 | vad_mode_ = mode; |
| 500 | return status; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 501 | } |
| 502 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 503 | int16_t ACMGenericCodec::InternalResetEncoder() { |
| 504 | // Call the codecs internal encoder initialization/reset function. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 505 | return InternalInitEncoder(&encoder_params_); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 506 | } |
| 507 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 508 | int16_t ACMGenericCodec::InitEncoder(WebRtcACMCodecParams* codec_params, |
| 509 | bool force_initialization) { |
| 510 | WriteLockScoped lockCodec(codec_wrapper_lock_); |
| 511 | ReadLockScoped lockNetEq(*neteq_decode_lock_); |
| 512 | return InitEncoderSafe(codec_params, force_initialization); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 513 | } |
| 514 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 515 | int16_t ACMGenericCodec::InitEncoderSafe(WebRtcACMCodecParams* codec_params, |
| 516 | bool force_initialization) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 517 | // Check if we got a valid set of parameters. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 518 | int mirrorID; |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 519 | int codec_number = ACMCodecDB::CodecNumber(&(codec_params->codec_inst), |
| 520 | &mirrorID); |
| 521 | if (codec_number < 0) { |
| 522 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 523 | "InitEncoderSafe: error, codec number negative"); |
| 524 | return -1; |
| 525 | } |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 526 | // Check if the parameters are for this codec. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 527 | if ((codec_id_ >= 0) && (codec_id_ != codec_number) && |
| 528 | (codec_id_ != mirrorID)) { |
| 529 | // The current codec is not the same as the one given by codec_params. |
| 530 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
| 531 | "InitEncoderSafe: current codec is not the same as the one " |
| 532 | "given by codec_params"); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 533 | return -1; |
| 534 | } |
| 535 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 536 | if (!CanChangeEncodingParam(codec_params->codec_inst)) { |
| 537 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 538 | "InitEncoderSafe: cannot change encoding parameters"); |
| 539 | return -1; |
| 540 | } |
| 541 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 542 | if (encoder_initialized_ && !force_initialization) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 543 | // The encoder is already initialized, and we don't want to force |
| 544 | // initialization. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 545 | return 0; |
| 546 | } |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 547 | int16_t status; |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 548 | if (!encoder_exist_) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 549 | // New encoder, start with creating. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 550 | encoder_initialized_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 551 | status = CreateEncoder(); |
| 552 | if (status < 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 553 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 554 | "InitEncoderSafe: cannot create encoder"); |
| 555 | return -1; |
| 556 | } else { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 557 | encoder_exist_ = true; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 558 | } |
| 559 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 560 | frame_len_smpl_ = (codec_params->codec_inst).pacsize; |
| 561 | num_channels_ = codec_params->codec_inst.channels; |
| 562 | status = InternalInitEncoder(codec_params); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 563 | if (status < 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 564 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 565 | "InitEncoderSafe: error in init encoder"); |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 566 | encoder_initialized_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 567 | return -1; |
| 568 | } else { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 569 | // Store encoder parameters. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 570 | memcpy(&encoder_params_, codec_params, sizeof(WebRtcACMCodecParams)); |
| 571 | encoder_initialized_ = true; |
| 572 | if (in_audio_ == NULL) { |
| 573 | in_audio_ = new int16_t[AUDIO_BUFFER_SIZE_W16]; |
| 574 | if (in_audio_ == NULL) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 575 | return -1; |
| 576 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 577 | memset(in_audio_, 0, AUDIO_BUFFER_SIZE_W16 * sizeof(int16_t)); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 578 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 579 | if (in_timestamp_ == NULL) { |
| 580 | in_timestamp_ = new uint32_t[TIMESTAMP_BUFFER_SIZE_W32]; |
| 581 | if (in_timestamp_ == NULL) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 582 | return -1; |
| 583 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 584 | memset(in_timestamp_, 0, sizeof(uint32_t) * TIMESTAMP_BUFFER_SIZE_W32); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 585 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 586 | is_audio_buff_fresh_ = true; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 587 | } |
tina.legrand@webrtc.org | 584b688 | 2013-08-27 07:33:51 | [diff] [blame] | 588 | status = SetVADSafe(&codec_params->enable_dtx, &codec_params->enable_vad, |
| 589 | &codec_params->vad_mode); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 590 | |
| 591 | return status; |
| 592 | } |
| 593 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 594 | // TODO(tlegrand): Remove the function CanChangeEncodingParam. Returns true |
| 595 | // for all codecs. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 596 | bool ACMGenericCodec::CanChangeEncodingParam(CodecInst& /*codec_inst*/) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 597 | return true; |
| 598 | } |
| 599 | |
pbos@webrtc.org | dd1b19d | 2013-07-31 15:54:00 | [diff] [blame] | 600 | void ACMGenericCodec::CurrentRate(int32_t& /* rate_bps */) { |
| 601 | return; |
| 602 | } |
| 603 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 604 | int16_t ACMGenericCodec::InitDecoder(WebRtcACMCodecParams* codec_params, |
| 605 | bool force_initialization) { |
| 606 | WriteLockScoped lockCodc(codec_wrapper_lock_); |
| 607 | WriteLockScoped lockNetEq(*neteq_decode_lock_); |
| 608 | return InitDecoderSafe(codec_params, force_initialization); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 609 | } |
| 610 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 611 | int16_t ACMGenericCodec::InitDecoderSafe(WebRtcACMCodecParams* codec_params, |
| 612 | bool force_initialization) { |
| 613 | int mirror_id; |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 614 | // Check if we got a valid set of parameters. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 615 | int codec_number = ACMCodecDB::ReceiverCodecNumber(&codec_params->codec_inst, |
| 616 | &mirror_id); |
| 617 | if (codec_number < 0) { |
| 618 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 619 | "InitDecoderSafe: error, invalid codec number"); |
| 620 | return -1; |
| 621 | } |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 622 | // Check if the parameters are for this codec. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 623 | if ((codec_id_ >= 0) && (codec_id_ != codec_number) && |
| 624 | (codec_id_ != mirror_id)) { |
| 625 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
| 626 | "InitDecoderSafe: current codec is not the same as the one " |
| 627 | "given by codec_params"); |
| 628 | // The current codec is not the same as the one given by codec_params. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 629 | return -1; |
| 630 | } |
| 631 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 632 | if (decoder_initialized_ && !force_initialization) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 633 | // The decoder is already initialized, and we don't want to force |
| 634 | // initialization. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 635 | return 0; |
| 636 | } |
| 637 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 638 | int16_t status; |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 639 | if (!decoder_exist_) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 640 | // New decoder, start with creating. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 641 | decoder_initialized_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 642 | status = CreateDecoder(); |
| 643 | if (status < 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 644 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 645 | "InitDecoderSafe: cannot create decoder"); |
| 646 | return -1; |
| 647 | } else { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 648 | decoder_exist_ = true; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 649 | } |
| 650 | } |
| 651 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 652 | status = InternalInitDecoder(codec_params); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 653 | if (status < 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 654 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 655 | "InitDecoderSafe: cannot init decoder"); |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 656 | decoder_initialized_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 657 | return -1; |
| 658 | } else { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 659 | // Store decoder parameters. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 660 | SaveDecoderParamSafe(codec_params); |
| 661 | decoder_initialized_ = true; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 662 | } |
| 663 | return 0; |
| 664 | } |
| 665 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 666 | int16_t ACMGenericCodec::ResetDecoder(int16_t payload_type) { |
| 667 | WriteLockScoped lockCodec(codec_wrapper_lock_); |
| 668 | WriteLockScoped lockNetEq(*neteq_decode_lock_); |
| 669 | return ResetDecoderSafe(payload_type); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 670 | } |
| 671 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 672 | int16_t ACMGenericCodec::ResetDecoderSafe(int16_t payload_type) { |
| 673 | WebRtcACMCodecParams decoder_params; |
| 674 | if (!decoder_exist_ || !decoder_initialized_) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 675 | return 0; |
| 676 | } |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 677 | // Initialization of the decoder should work for all the codec. For codecs |
| 678 | // that needs to keep some states an overloading implementation of |
| 679 | // |DecoderParamsSafe| exists. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 680 | DecoderParamsSafe(&decoder_params, static_cast<uint8_t>(payload_type)); |
| 681 | return InternalInitDecoder(&decoder_params); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 682 | } |
| 683 | |
| 684 | void ACMGenericCodec::ResetNoMissedSamples() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 685 | WriteLockScoped cs(codec_wrapper_lock_); |
| 686 | num_missed_samples_ = 0; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 687 | } |
| 688 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 689 | void ACMGenericCodec::IncreaseNoMissedSamples(const int16_t num_samples) { |
| 690 | num_missed_samples_ += num_samples; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 691 | } |
| 692 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 693 | // Get the number of missed samples, this can be public. |
| 694 | uint32_t ACMGenericCodec::NoMissedSamples() const { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 695 | ReadLockScoped cs(codec_wrapper_lock_); |
| 696 | return num_missed_samples_; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 697 | } |
| 698 | |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 699 | void ACMGenericCodec::DestructEncoder() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 700 | WriteLockScoped wl(codec_wrapper_lock_); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 701 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 702 | // Disable VAD and delete the instance. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 703 | if (ptr_vad_inst_ != NULL) { |
| 704 | WebRtcVad_Free(ptr_vad_inst_); |
| 705 | ptr_vad_inst_ = NULL; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 706 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 707 | vad_enabled_ = false; |
| 708 | vad_mode_ = VADNormal; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 709 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 710 | // Disable DTX and delete the instance. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 711 | dtx_enabled_ = false; |
| 712 | if (ptr_dtx_inst_ != NULL) { |
| 713 | WebRtcCng_FreeEnc(ptr_dtx_inst_); |
| 714 | ptr_dtx_inst_ = NULL; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 715 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 716 | num_lpc_params_ = kNewCNGNumPLCParams; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 717 | |
| 718 | DestructEncoderSafe(); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 719 | } |
| 720 | |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 721 | void ACMGenericCodec::DestructDecoder() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 722 | WriteLockScoped wl(codec_wrapper_lock_); |
| 723 | decoder_params_.codec_inst.pltype = -1; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 724 | DestructDecoderSafe(); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 725 | } |
| 726 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 727 | int16_t ACMGenericCodec::SetBitRate(const int32_t bitrate_bps) { |
| 728 | WriteLockScoped wl(codec_wrapper_lock_); |
| 729 | return SetBitRateSafe(bitrate_bps); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 730 | } |
| 731 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 732 | int16_t ACMGenericCodec::SetBitRateSafe(const int32_t bitrate_bps) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 733 | // If the codec can change the bit-rate this function is overloaded. |
| 734 | // Otherwise the only acceptable value is the one that is in the database. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 735 | CodecInst codec_params; |
| 736 | if (ACMCodecDB::Codec(codec_id_, &codec_params) < 0) { |
| 737 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 738 | "SetBitRateSafe: error in ACMCodecDB::Codec"); |
| 739 | return -1; |
| 740 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 741 | if (codec_params.rate != bitrate_bps) { |
| 742 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 743 | "SetBitRateSafe: rate value is not acceptable"); |
| 744 | return -1; |
| 745 | } else { |
| 746 | return 0; |
| 747 | } |
| 748 | } |
| 749 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 750 | // iSAC specific functions: |
| 751 | int32_t ACMGenericCodec::GetEstimatedBandwidth() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 752 | WriteLockScoped wl(codec_wrapper_lock_); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 753 | return GetEstimatedBandwidthSafe(); |
| 754 | } |
| 755 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 756 | int32_t ACMGenericCodec::GetEstimatedBandwidthSafe() { |
| 757 | // All codecs but iSAC will return -1. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 758 | return -1; |
| 759 | } |
| 760 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 761 | int32_t ACMGenericCodec::SetEstimatedBandwidth(int32_t estimated_bandwidth) { |
| 762 | WriteLockScoped wl(codec_wrapper_lock_); |
| 763 | return SetEstimatedBandwidthSafe(estimated_bandwidth); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 764 | } |
| 765 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 766 | int32_t ACMGenericCodec::SetEstimatedBandwidthSafe( |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 767 | int32_t /*estimated_bandwidth*/) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 768 | // All codecs but iSAC will return -1. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 769 | return -1; |
| 770 | } |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 771 | // End of iSAC specific functions. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 772 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 773 | int32_t ACMGenericCodec::GetRedPayload(uint8_t* red_payload, |
| 774 | int16_t* payload_bytes) { |
| 775 | WriteLockScoped wl(codec_wrapper_lock_); |
| 776 | return GetRedPayloadSafe(red_payload, payload_bytes); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 777 | } |
| 778 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 779 | int32_t ACMGenericCodec::GetRedPayloadSafe(uint8_t* /* red_payload */, |
| 780 | int16_t* /* payload_bytes */) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 781 | return -1; // Do nothing by default. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 782 | } |
| 783 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 784 | int16_t ACMGenericCodec::CreateEncoder() { |
| 785 | int16_t status = 0; |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 786 | if (!encoder_exist_) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 787 | status = InternalCreateEncoder(); |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 788 | // We just created the codec and obviously it is not initialized. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 789 | encoder_initialized_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 790 | } |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 791 | if (status < 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 792 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 793 | "CreateEncoder: error in internal create encoder"); |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 794 | encoder_exist_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 795 | } else { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 796 | encoder_exist_ = true; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 797 | } |
| 798 | return status; |
| 799 | } |
| 800 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 801 | int16_t ACMGenericCodec::CreateDecoder() { |
| 802 | int16_t status = 0; |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 803 | if (!decoder_exist_) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 804 | status = InternalCreateDecoder(); |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 805 | // Decoder just created and obviously it is not initialized. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 806 | decoder_initialized_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 807 | } |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 808 | if (status < 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 809 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 810 | "CreateDecoder: error in internal create decoder"); |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 811 | decoder_exist_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 812 | } else { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 813 | decoder_exist_ = true; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 814 | } |
| 815 | return status; |
| 816 | } |
| 817 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 818 | void ACMGenericCodec::DestructEncoderInst(void* ptr_inst) { |
| 819 | if (ptr_inst != NULL) { |
| 820 | WriteLockScoped lockCodec(codec_wrapper_lock_); |
| 821 | ReadLockScoped lockNetEq(*neteq_decode_lock_); |
| 822 | InternalDestructEncoderInst(ptr_inst); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 823 | } |
| 824 | } |
| 825 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 826 | // Get the current audio buffer including read and write states, and timestamps. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 827 | int16_t ACMGenericCodec::AudioBuffer(WebRtcACMAudioBuff& audio_buff) { |
| 828 | ReadLockScoped cs(codec_wrapper_lock_); |
| 829 | memcpy(audio_buff.in_audio, in_audio_, |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 830 | AUDIO_BUFFER_SIZE_W16 * sizeof(int16_t)); |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 831 | audio_buff.in_audio_ix_read = in_audio_ix_read_; |
| 832 | audio_buff.in_audio_ix_write = in_audio_ix_write_; |
| 833 | memcpy(audio_buff.in_timestamp, in_timestamp_, |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 834 | TIMESTAMP_BUFFER_SIZE_W32 * sizeof(uint32_t)); |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 835 | audio_buff.in_timestamp_ix_write = in_timestamp_ix_write_; |
| 836 | audio_buff.last_timestamp = last_timestamp_; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 837 | return 0; |
| 838 | } |
| 839 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 840 | // Set the audio buffer. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 841 | int16_t ACMGenericCodec::SetAudioBuffer(WebRtcACMAudioBuff& audio_buff) { |
| 842 | WriteLockScoped cs(codec_wrapper_lock_); |
| 843 | memcpy(in_audio_, audio_buff.in_audio, |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 844 | AUDIO_BUFFER_SIZE_W16 * sizeof(int16_t)); |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 845 | in_audio_ix_read_ = audio_buff.in_audio_ix_read; |
| 846 | in_audio_ix_write_ = audio_buff.in_audio_ix_write; |
| 847 | memcpy(in_timestamp_, audio_buff.in_timestamp, |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 848 | TIMESTAMP_BUFFER_SIZE_W32 * sizeof(uint32_t)); |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 849 | in_timestamp_ix_write_ = audio_buff.in_timestamp_ix_write; |
| 850 | last_timestamp_ = audio_buff.last_timestamp; |
| 851 | is_audio_buff_fresh_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 852 | return 0; |
| 853 | } |
| 854 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 855 | uint32_t ACMGenericCodec::LastEncodedTimestamp() const { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 856 | ReadLockScoped cs(codec_wrapper_lock_); |
| 857 | return last_encoded_timestamp_; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 858 | } |
| 859 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 860 | uint32_t ACMGenericCodec::EarliestTimestamp() const { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 861 | ReadLockScoped cs(codec_wrapper_lock_); |
| 862 | return in_timestamp_[0]; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 863 | } |
| 864 | |
tina.legrand@webrtc.org | 584b688 | 2013-08-27 07:33:51 | [diff] [blame] | 865 | int16_t ACMGenericCodec::SetVAD(bool* enable_dtx, bool* enable_vad, |
| 866 | ACMVADMode* mode) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 867 | WriteLockScoped cs(codec_wrapper_lock_); |
| 868 | return SetVADSafe(enable_dtx, enable_vad, mode); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 869 | } |
| 870 | |
tina.legrand@webrtc.org | 584b688 | 2013-08-27 07:33:51 | [diff] [blame] | 871 | int16_t ACMGenericCodec::SetVADSafe(bool* enable_dtx, bool* enable_vad, |
| 872 | ACMVADMode* mode) { |
| 873 | if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "OPUS") || |
| 874 | encoder_params_.codec_inst.channels == 2 ) { |
| 875 | // VAD/DTX is not supported for Opus (even if sending mono), or other |
| 876 | // stereo codecs. |
| 877 | DisableDTX(); |
| 878 | DisableVAD(); |
| 879 | *enable_dtx = false; |
| 880 | *enable_vad = false; |
| 881 | return 0; |
| 882 | } |
| 883 | |
| 884 | if (*enable_dtx) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 885 | // Make G729 AnnexB a special case. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 886 | if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "G729") |
| 887 | && !has_internal_dtx_) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 888 | if (ACMGenericCodec::EnableDTX() < 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 889 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 890 | "SetVADSafe: error in enable DTX"); |
tina.legrand@webrtc.org | 584b688 | 2013-08-27 07:33:51 | [diff] [blame] | 891 | *enable_dtx = false; |
| 892 | *enable_vad = vad_enabled_; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 893 | return -1; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 894 | } |
| 895 | } else { |
| 896 | if (EnableDTX() < 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 897 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 898 | "SetVADSafe: error in enable DTX"); |
tina.legrand@webrtc.org | 584b688 | 2013-08-27 07:33:51 | [diff] [blame] | 899 | *enable_dtx = false; |
| 900 | *enable_vad = vad_enabled_; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 901 | return -1; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 902 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 903 | } |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 904 | |
tina.legrand@webrtc.org | 584b688 | 2013-08-27 07:33:51 | [diff] [blame] | 905 | // If codec does not have internal DTX (normal case) enabling DTX requires |
| 906 | // an active VAD. '*enable_dtx == true' overwrites VAD status. |
| 907 | // If codec has internal DTX, practically we don't need WebRtc VAD, however, |
| 908 | // we let the user to turn it on if they need call-backs on silence. |
| 909 | if (!has_internal_dtx_) { |
| 910 | // DTX is enabled, and VAD will be activated. |
| 911 | *enable_vad = true; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 912 | } |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 913 | } else { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 914 | // Make G729 AnnexB a special case. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 915 | if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "G729") |
| 916 | && !has_internal_dtx_) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 917 | ACMGenericCodec::DisableDTX(); |
tina.legrand@webrtc.org | 584b688 | 2013-08-27 07:33:51 | [diff] [blame] | 918 | *enable_dtx = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 919 | } else { |
| 920 | DisableDTX(); |
tina.legrand@webrtc.org | 584b688 | 2013-08-27 07:33:51 | [diff] [blame] | 921 | *enable_dtx = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 922 | } |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 923 | } |
tina.legrand@webrtc.org | 584b688 | 2013-08-27 07:33:51 | [diff] [blame] | 924 | |
| 925 | int16_t status = (*enable_vad) ? EnableVAD(*mode) : DisableVAD(); |
| 926 | if (status < 0) { |
| 927 | // Failed to set VAD, disable DTX. |
| 928 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
| 929 | "SetVADSafe: error in enable VAD"); |
| 930 | DisableDTX(); |
| 931 | *enable_dtx = false; |
| 932 | *enable_vad = false; |
| 933 | } |
| 934 | return status; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 935 | } |
| 936 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 937 | int16_t ACMGenericCodec::EnableDTX() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 938 | if (has_internal_dtx_) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 939 | // We should not be here if we have internal DTX this function should be |
| 940 | // overloaded by the derived class in this case. |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 941 | return -1; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 942 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 943 | if (!dtx_enabled_) { |
| 944 | if (WebRtcCng_CreateEnc(&ptr_dtx_inst_) < 0) { |
| 945 | ptr_dtx_inst_ = NULL; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 946 | return -1; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 947 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 948 | uint16_t freq_hz; |
| 949 | EncoderSampFreq(freq_hz); |
| 950 | if (WebRtcCng_InitEnc(ptr_dtx_inst_, freq_hz, kCngSidIntervalMsec, |
| 951 | num_lpc_params_) < 0) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 952 | // Couldn't initialize, has to return -1, and free the memory. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 953 | WebRtcCng_FreeEnc(ptr_dtx_inst_); |
| 954 | ptr_dtx_inst_ = NULL; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 955 | return -1; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 956 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 957 | dtx_enabled_ = true; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 958 | } |
| 959 | return 0; |
| 960 | } |
| 961 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 962 | int16_t ACMGenericCodec::DisableDTX() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 963 | if (has_internal_dtx_) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 964 | // We should not be here if we have internal DTX this function should be |
| 965 | // overloaded by the derived class in this case. |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 966 | return -1; |
| 967 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 968 | if (ptr_dtx_inst_ != NULL) { |
| 969 | WebRtcCng_FreeEnc(ptr_dtx_inst_); |
| 970 | ptr_dtx_inst_ = NULL; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 971 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 972 | dtx_enabled_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 973 | return 0; |
| 974 | } |
| 975 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 976 | int16_t ACMGenericCodec::EnableVAD(ACMVADMode mode) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 977 | if ((mode < VADNormal) || (mode > VADVeryAggr)) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 978 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 979 | "EnableVAD: error in VAD mode range"); |
| 980 | return -1; |
| 981 | } |
| 982 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 983 | if (!vad_enabled_) { |
| 984 | if (WebRtcVad_Create(&ptr_vad_inst_) < 0) { |
| 985 | ptr_vad_inst_ = NULL; |
| 986 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 987 | "EnableVAD: error in create VAD"); |
| 988 | return -1; |
| 989 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 990 | if (WebRtcVad_Init(ptr_vad_inst_) < 0) { |
| 991 | WebRtcVad_Free(ptr_vad_inst_); |
| 992 | ptr_vad_inst_ = NULL; |
| 993 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 994 | "EnableVAD: error in init VAD"); |
| 995 | return -1; |
| 996 | } |
| 997 | } |
| 998 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 999 | // Set the VAD mode to the given value. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1000 | if (WebRtcVad_set_mode(ptr_vad_inst_, mode) < 0) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1001 | // We failed to set the mode and we have to return -1. If we already have a |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1002 | // working VAD (vad_enabled_ == true) then we leave it to work. Otherwise, |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1003 | // the following will be executed. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1004 | if (!vad_enabled_) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1005 | // We just created the instance but cannot set the mode we have to free |
| 1006 | // the memory. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1007 | WebRtcVad_Free(ptr_vad_inst_); |
| 1008 | ptr_vad_inst_ = NULL; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1009 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1010 | WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1011 | "EnableVAD: failed to set the VAD mode"); |
| 1012 | return -1; |
| 1013 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1014 | vad_mode_ = mode; |
| 1015 | vad_enabled_ = true; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1016 | return 0; |
| 1017 | } |
| 1018 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1019 | int16_t ACMGenericCodec::DisableVAD() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1020 | if (ptr_vad_inst_ != NULL) { |
| 1021 | WebRtcVad_Free(ptr_vad_inst_); |
| 1022 | ptr_vad_inst_ = NULL; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1023 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1024 | vad_enabled_ = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1025 | return 0; |
| 1026 | } |
| 1027 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1028 | int32_t ACMGenericCodec::ReplaceInternalDTX(const bool replace_internal_dtx) { |
| 1029 | WriteLockScoped cs(codec_wrapper_lock_); |
| 1030 | return ReplaceInternalDTXSafe(replace_internal_dtx); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1031 | } |
| 1032 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1033 | int32_t ACMGenericCodec::ReplaceInternalDTXSafe( |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1034 | const bool /* replace_internal_dtx */) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1035 | return -1; |
| 1036 | } |
| 1037 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1038 | int32_t ACMGenericCodec::IsInternalDTXReplaced(bool* internal_dtx_replaced) { |
| 1039 | WriteLockScoped cs(codec_wrapper_lock_); |
| 1040 | return IsInternalDTXReplacedSafe(internal_dtx_replaced); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1041 | } |
| 1042 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1043 | int32_t ACMGenericCodec::IsInternalDTXReplacedSafe( |
| 1044 | bool* internal_dtx_replaced) { |
| 1045 | *internal_dtx_replaced = false; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1046 | return 0; |
| 1047 | } |
| 1048 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1049 | int16_t ACMGenericCodec::ProcessFrameVADDTX(uint8_t* bitstream, |
| 1050 | int16_t* bitstream_len_byte, |
| 1051 | int16_t* samples_processed) { |
| 1052 | if (!vad_enabled_) { |
| 1053 | // VAD not enabled, set all |vad_lable_[]| to 1 (speech detected). |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1054 | for (int n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1055 | vad_label_[n] = 1; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1056 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1057 | *samples_processed = 0; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1058 | return 0; |
| 1059 | } |
| 1060 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1061 | uint16_t freq_hz; |
| 1062 | EncoderSampFreq(freq_hz); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1063 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1064 | // Calculate number of samples in 10 ms blocks, and number ms in one frame. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1065 | int16_t samples_in_10ms = static_cast<int16_t>(freq_hz / 100); |
| 1066 | int32_t frame_len_ms = static_cast<int32_t>(frame_len_smpl_) * 1000 / freq_hz; |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1067 | int16_t status; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1068 | |
| 1069 | // Vector for storing maximum 30 ms of mono audio at 48 kHz. |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1070 | int16_t audio[1440]; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1071 | |
| 1072 | // Calculate number of VAD-blocks to process, and number of samples in each |
| 1073 | // block. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1074 | int num_samples_to_process[2]; |
| 1075 | if (frame_len_ms == 40) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1076 | // 20 ms in each VAD block. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1077 | num_samples_to_process[0] = num_samples_to_process[1] = 2 * samples_in_10ms; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1078 | } else { |
| 1079 | // For 10-30 ms framesizes, second VAD block will be size zero ms, |
| 1080 | // for 50 and 60 ms first VAD block will be 30 ms. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1081 | num_samples_to_process[0] = |
| 1082 | (frame_len_ms > 30) ? 3 * samples_in_10ms : frame_len_smpl_; |
| 1083 | num_samples_to_process[1] = frame_len_smpl_ - num_samples_to_process[0]; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1084 | } |
| 1085 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1086 | int offset = 0; |
| 1087 | int loops = (num_samples_to_process[1] > 0) ? 2 : 1; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1088 | for (int i = 0; i < loops; i++) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1089 | // TODO(turajs): Do we need to care about VAD together with stereo? |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1090 | // If stereo, calculate mean of the two channels. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1091 | if (num_channels_ == 2) { |
| 1092 | for (int j = 0; j < num_samples_to_process[i]; j++) { |
| 1093 | audio[j] = (in_audio_[(offset + j) * 2] + |
| 1094 | in_audio_[(offset + j) * 2 + 1]) / 2; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1095 | } |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1096 | offset = num_samples_to_process[0]; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1097 | } else { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1098 | // Mono, copy data from in_audio_ to continue work on. |
| 1099 | memcpy(audio, in_audio_, sizeof(int16_t) * num_samples_to_process[i]); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1100 | } |
| 1101 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1102 | // Call VAD. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1103 | status = static_cast<int16_t>(WebRtcVad_Process(ptr_vad_inst_, |
| 1104 | static_cast<int>(freq_hz), |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1105 | audio, |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1106 | num_samples_to_process[i])); |
| 1107 | vad_label_[i] = status; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1108 | |
| 1109 | if (status < 0) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1110 | // This will force that the data be removed from the buffer. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1111 | *samples_processed += num_samples_to_process[i]; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1112 | return -1; |
| 1113 | } |
| 1114 | |
| 1115 | // If VAD decision non-active, update DTX. NOTE! We only do this if the |
| 1116 | // first part of a frame gets the VAD decision "inactive". Otherwise DTX |
| 1117 | // might say it is time to transmit SID frame, but we will encode the whole |
| 1118 | // frame, because the first part is active. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1119 | *samples_processed = 0; |
| 1120 | if ((status == 0) && (i == 0) && dtx_enabled_ && !has_internal_dtx_) { |
| 1121 | int16_t bitstream_len; |
| 1122 | int num_10ms_frames = num_samples_to_process[i] / samples_in_10ms; |
| 1123 | *bitstream_len_byte = 0; |
| 1124 | for (int n = 0; n < num_10ms_frames; n++) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1125 | // This block is (passive) && (vad enabled). If first CNG after |
| 1126 | // speech, force SID by setting last parameter to "1". |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1127 | status = WebRtcCng_Encode(ptr_dtx_inst_, &audio[n * samples_in_10ms], |
| 1128 | samples_in_10ms, bitstream, &bitstream_len, |
| 1129 | !prev_frame_cng_); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1130 | if (status < 0) { |
| 1131 | return -1; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1132 | } |
| 1133 | |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1134 | // Update previous frame was CNG. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1135 | prev_frame_cng_ = 1; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1136 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1137 | *samples_processed += samples_in_10ms * num_channels_; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1138 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1139 | // |bitstream_len_byte| will only be > 0 once per 100 ms. |
| 1140 | *bitstream_len_byte += bitstream_len; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1141 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1142 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1143 | // Check if all samples got processed by the DTX. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1144 | if (*samples_processed != num_samples_to_process[i] * num_channels_) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1145 | // Set to zero since something went wrong. Shouldn't happen. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1146 | *samples_processed = 0; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1147 | } |
| 1148 | } else { |
| 1149 | // Update previous frame was not CNG. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1150 | prev_frame_cng_ = 0; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1151 | } |
| 1152 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1153 | if (*samples_processed > 0) { |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1154 | // The block contains inactive speech, and is processed by DTX. |
| 1155 | // Discontinue running VAD. |
| 1156 | break; |
| 1157 | } |
| 1158 | } |
| 1159 | |
| 1160 | return status; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1161 | } |
| 1162 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1163 | int16_t ACMGenericCodec::SamplesLeftToEncode() { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1164 | ReadLockScoped rl(codec_wrapper_lock_); |
| 1165 | return (frame_len_smpl_ <= in_audio_ix_write_) ? 0 : |
| 1166 | (frame_len_smpl_ - in_audio_ix_write_); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1167 | } |
| 1168 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1169 | void ACMGenericCodec::SetUniqueID(const uint32_t id) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1170 | unique_id_ = id; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1171 | } |
| 1172 | |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1173 | bool ACMGenericCodec::IsAudioBufferFresh() const { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1174 | ReadLockScoped rl(codec_wrapper_lock_); |
| 1175 | return is_audio_buff_fresh_; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1176 | } |
| 1177 | |
pbos@webrtc.org | dd1b19d | 2013-07-31 15:54:00 | [diff] [blame] | 1178 | int16_t ACMGenericCodec::UpdateDecoderSampFreq(int16_t /* codec_id */) { |
| 1179 | return 0; |
| 1180 | } |
| 1181 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1182 | // This function is replaced by codec specific functions for some codecs. |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1183 | int16_t ACMGenericCodec::EncoderSampFreq(uint16_t& samp_freq_hz) { |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1184 | int32_t f; |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1185 | f = ACMCodecDB::CodecFreq(codec_id_); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1186 | if (f < 0) { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1187 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1188 | "EncoderSampFreq: codec frequency is negative"); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1189 | return -1; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1190 | } else { |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1191 | samp_freq_hz = static_cast<uint16_t>(f); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1192 | return 0; |
| 1193 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1194 | } |
| 1195 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1196 | int32_t ACMGenericCodec::ConfigISACBandwidthEstimator( |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1197 | const uint8_t /* init_frame_size_msec */, |
| 1198 | const uint16_t /* init_rate_bit_per_sec */, |
| 1199 | const bool /* enforce_frame_size */) { |
| 1200 | WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_, |
| 1201 | "The send-codec is not iSAC, failed to config iSAC bandwidth " |
| 1202 | "estimator."); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1203 | return -1; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1204 | } |
| 1205 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1206 | int32_t ACMGenericCodec::SetISACMaxRate( |
| 1207 | const uint32_t /* max_rate_bit_per_sec */) { |
| 1208 | WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1209 | "The send-codec is not iSAC, failed to set iSAC max rate."); |
| 1210 | return -1; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 | [diff] [blame] | 1211 | } |
| 1212 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1213 | int32_t ACMGenericCodec::SetISACMaxPayloadSize( |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1214 | const uint16_t /* max_payload_len_bytes */) { |
| 1215 | WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_, |
| 1216 | "The send-codec is not iSAC, failed to set iSAC max " |
| 1217 | "payload-size."); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1218 | return -1; |
| 1219 | } |
| 1220 | |
| 1221 | void ACMGenericCodec::SaveDecoderParam( |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1222 | const WebRtcACMCodecParams* codec_params) { |
| 1223 | WriteLockScoped wl(codec_wrapper_lock_); |
| 1224 | SaveDecoderParamSafe(codec_params); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1225 | } |
| 1226 | |
| 1227 | void ACMGenericCodec::SaveDecoderParamSafe( |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1228 | const WebRtcACMCodecParams* codec_params) { |
| 1229 | memcpy(&decoder_params_, codec_params, sizeof(WebRtcACMCodecParams)); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1230 | } |
| 1231 | |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1232 | int16_t ACMGenericCodec::UpdateEncoderSampFreq( |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1233 | uint16_t /* samp_freq_hz */) { |
| 1234 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
| 1235 | "It is asked for a change in smapling frequency while the " |
| 1236 | "current send-codec supports only one sampling rate."); |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1237 | return -1; |
| 1238 | } |
| 1239 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1240 | void ACMGenericCodec::SetIsMaster(bool is_master) { |
| 1241 | WriteLockScoped wl(codec_wrapper_lock_); |
| 1242 | is_master_ = is_master; |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1243 | } |
| 1244 | |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1245 | int16_t ACMGenericCodec::REDPayloadISAC(const int32_t /* isac_rate */, |
| 1246 | const int16_t /* isac_bw_estimate */, |
tina.legrand@webrtc.org | 2bd7fc7 | 2012-11-13 14:09:35 | [diff] [blame] | 1247 | uint8_t* /* payload */, |
turaj@webrtc.org | 4c9b819 | 2012-12-13 22:46:43 | [diff] [blame] | 1248 | int16_t* /* payload_len_bytes */) { |
| 1249 | WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1250 | "Error: REDPayloadISAC is an iSAC specific function"); |
| 1251 | return -1; |
| 1252 | } |
| 1253 | |
pbos@webrtc.org | dd1b19d | 2013-07-31 15:54:00 | [diff] [blame] | 1254 | bool ACMGenericCodec::IsTrueStereoCodec() { return false; } |
| 1255 | |
turaj@webrtc.org | ed0b4fb | 2013-09-13 23:06:59 | [diff] [blame] | 1256 | } // namespace acm1 |
| 1257 | |
tina.legrand@webrtc.org | c0cf1db | 2012-11-05 09:35:51 | [diff] [blame] | 1258 | } // namespace webrtc |