Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_ | 11 #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_ |
| 12 #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_ | 12 #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_ |
| 13 | 13 |
| 14 #include "webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_i sac.h" | 14 #include "webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_i sac.h" |
| 15 | 15 |
| 16 #include <algorithm> | 16 #include <algorithm> |
| 17 | 17 |
| 18 #include "webrtc/base/checks.h" | 18 #include "webrtc/base/checks.h" |
| 19 #include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h" | 19 #include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h" |
| 20 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" | |
| 21 | 20 |
| 22 namespace webrtc { | 21 namespace webrtc { |
| 23 | 22 |
| 24 const int kIsacPayloadType = 103; | 23 const int kIsacPayloadType = 103; |
| 25 const int kDefaultBitRate = 32000; | 24 const int kDefaultBitRate = 32000; |
| 26 | 25 |
| 27 template <typename T> | 26 template <typename T> |
| 28 AudioEncoderDecoderIsacT<T>::Config::Config() | 27 AudioEncoderIsacT<T>::Config::Config() |
| 29 : payload_type(kIsacPayloadType), | 28 : bwinfo(nullptr), |
| 29 payload_type(kIsacPayloadType), | |
| 30 sample_rate_hz(16000), | 30 sample_rate_hz(16000), |
| 31 frame_size_ms(30), | 31 frame_size_ms(30), |
| 32 bit_rate(kDefaultBitRate), | 32 bit_rate(kDefaultBitRate), |
| 33 max_payload_size_bytes(-1), | 33 max_payload_size_bytes(-1), |
| 34 max_bit_rate(-1), | 34 max_bit_rate(-1), |
| 35 adaptive_mode(false), | 35 adaptive_mode(false), |
| 36 enforce_frame_size(false) { | 36 enforce_frame_size(false) { |
| 37 } | 37 } |
| 38 | 38 |
| 39 template <typename T> | 39 template <typename T> |
| 40 bool AudioEncoderDecoderIsacT<T>::Config::IsOk() const { | 40 bool AudioEncoderIsacT<T>::Config::IsOk() const { |
| 41 if (max_bit_rate < 32000 && max_bit_rate != -1) | 41 if (max_bit_rate < 32000 && max_bit_rate != -1) |
| 42 return false; | 42 return false; |
| 43 if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1) | 43 if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1) |
| 44 return false; | 44 return false; |
| 45 if (adaptive_mode && !bwinfo) | |
| 46 return false; | |
| 45 switch (sample_rate_hz) { | 47 switch (sample_rate_hz) { |
| 46 case 16000: | 48 case 16000: |
| 47 if (max_bit_rate > 53400) | 49 if (max_bit_rate > 53400) |
| 48 return false; | 50 return false; |
| 49 if (max_payload_size_bytes > 400) | 51 if (max_payload_size_bytes > 400) |
| 50 return false; | 52 return false; |
| 51 return (frame_size_ms == 30 || frame_size_ms == 60) && | 53 return (frame_size_ms == 30 || frame_size_ms == 60) && |
| 52 (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 32000)); | 54 (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 32000)); |
| 53 case 32000: | 55 case 32000: |
| 54 case 48000: | 56 case 48000: |
| 55 if (max_bit_rate > 160000) | 57 if (max_bit_rate > 160000) |
| 56 return false; | 58 return false; |
| 57 if (max_payload_size_bytes > 600) | 59 if (max_payload_size_bytes > 600) |
| 58 return false; | 60 return false; |
| 59 return T::has_swb && | 61 return T::has_swb && |
| 60 (frame_size_ms == 30 && | 62 (frame_size_ms == 30 && |
| 61 (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 56000))); | 63 (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 56000))); |
| 62 default: | 64 default: |
| 63 return false; | 65 return false; |
| 64 } | 66 } |
| 65 } | 67 } |
| 66 | 68 |
| 67 template <typename T> | 69 template <typename T> |
| 68 AudioEncoderDecoderIsacT<T>::AudioEncoderDecoderIsacT(const Config& config) | 70 AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config) |
| 69 : payload_type_(config.payload_type), | 71 : payload_type_(config.payload_type), |
| 70 state_lock_(CriticalSectionWrapper::CreateCriticalSection()), | 72 bwinfo_(config.bwinfo), |
| 71 decoder_sample_rate_hz_(0), | |
| 72 lock_(CriticalSectionWrapper::CreateCriticalSection()), | |
| 73 packet_in_progress_(false), | 73 packet_in_progress_(false), |
| 74 target_bitrate_bps_(config.adaptive_mode ? -1 : (config.bit_rate == 0 | 74 target_bitrate_bps_(config.adaptive_mode ? -1 : (config.bit_rate == 0 |
| 75 ? kDefaultBitRate | 75 ? kDefaultBitRate |
| 76 : config.bit_rate)) { | 76 : config.bit_rate)) { |
| 77 CHECK(config.IsOk()); | 77 CHECK(config.IsOk()); |
| 78 CHECK_EQ(0, T::Create(&isac_state_)); | 78 CHECK_EQ(0, T::Create(&isac_state_)); |
| 79 CHECK_EQ(0, T::EncoderInit(isac_state_, config.adaptive_mode ? 0 : 1)); | 79 CHECK_EQ(0, T::EncoderInit(isac_state_, config.adaptive_mode ? 0 : 1)); |
| 80 CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz)); | 80 CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz)); |
| 81 const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate; | 81 const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate; |
| 82 if (config.adaptive_mode) { | 82 if (config.adaptive_mode) { |
| 83 CHECK_EQ(0, T::ControlBwe(isac_state_, bit_rate, config.frame_size_ms, | 83 CHECK_EQ(0, T::ControlBwe(isac_state_, bit_rate, config.frame_size_ms, |
| 84 config.enforce_frame_size)); | 84 config.enforce_frame_size)); |
| 85 } else { | 85 } else { |
| 86 CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms)); | 86 CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms)); |
| 87 } | 87 } |
| 88 // When config.sample_rate_hz is set to 48000 Hz (iSAC-fb), the decoder is | |
| 89 // still set to 32000 Hz, since there is no full-band mode in the decoder. | |
| 90 CHECK_EQ(0, T::SetDecSampRate(isac_state_, | |
| 91 std::min(config.sample_rate_hz, 32000))); | |
| 92 if (config.max_payload_size_bytes != -1) | 88 if (config.max_payload_size_bytes != -1) |
| 93 CHECK_EQ(0, | 89 CHECK_EQ(0, |
| 94 T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes)); | 90 T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes)); |
| 95 if (config.max_bit_rate != -1) | 91 if (config.max_bit_rate != -1) |
| 96 CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate)); | 92 CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate)); |
| 97 CHECK_EQ(0, T::DecoderInit(isac_state_)); | 93 |
| 94 // When config.sample_rate_hz is set to 48000 Hz (iSAC-fb), the decoder is | |
| 95 // still set to 32000 Hz, since there is no full-band mode in the decoder. | |
| 96 const int decoder_sample_rate_hz = std::min(config.sample_rate_hz, 32000); | |
| 97 | |
| 98 // Set the decoder sample rate even though we just use the encoder. This | |
| 99 // doesn't appear to be necessary to produce a valid encoding, but without it | |
| 100 // we get an encoding that isn't bit-for-bit identical with what a combined | |
| 101 // encoder+decoder object produces. | |
| 102 CHECK_EQ(0, T::SetDecSampRate(isac_state_, decoder_sample_rate_hz)); | |
| 98 } | 103 } |
| 99 | 104 |
| 100 template <typename T> | 105 template <typename T> |
| 101 AudioEncoderDecoderIsacT<T>::~AudioEncoderDecoderIsacT() { | 106 AudioEncoderIsacT<T>::~AudioEncoderIsacT() { |
| 102 CHECK_EQ(0, T::Free(isac_state_)); | 107 CHECK_EQ(0, T::Free(isac_state_)); |
| 103 } | 108 } |
| 104 | 109 |
| 105 template <typename T> | 110 template <typename T> |
| 106 int AudioEncoderDecoderIsacT<T>::SampleRateHz() const { | 111 int AudioEncoderIsacT<T>::SampleRateHz() const { |
| 107 CriticalSectionScoped cs(state_lock_.get()); | |
| 108 return T::EncSampRate(isac_state_); | 112 return T::EncSampRate(isac_state_); |
| 109 } | 113 } |
| 110 | 114 |
| 111 template <typename T> | 115 template <typename T> |
| 112 int AudioEncoderDecoderIsacT<T>::NumChannels() const { | 116 int AudioEncoderIsacT<T>::NumChannels() const { |
| 113 return 1; | 117 return 1; |
| 114 } | 118 } |
| 115 | 119 |
| 116 template <typename T> | 120 template <typename T> |
| 117 size_t AudioEncoderDecoderIsacT<T>::MaxEncodedBytes() const { | 121 size_t AudioEncoderIsacT<T>::MaxEncodedBytes() const { |
| 118 return kSufficientEncodeBufferSizeBytes; | 122 return kSufficientEncodeBufferSizeBytes; |
| 119 } | 123 } |
| 120 | 124 |
| 121 template <typename T> | 125 template <typename T> |
| 122 int AudioEncoderDecoderIsacT<T>::Num10MsFramesInNextPacket() const { | 126 int AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const { |
| 123 CriticalSectionScoped cs(state_lock_.get()); | |
| 124 const int samples_in_next_packet = T::GetNewFrameLen(isac_state_); | 127 const int samples_in_next_packet = T::GetNewFrameLen(isac_state_); |
| 125 return rtc::CheckedDivExact(samples_in_next_packet, | 128 return rtc::CheckedDivExact(samples_in_next_packet, |
| 126 rtc::CheckedDivExact(SampleRateHz(), 100)); | 129 rtc::CheckedDivExact(SampleRateHz(), 100)); |
| 127 } | 130 } |
| 128 | 131 |
| 129 template <typename T> | 132 template <typename T> |
| 130 int AudioEncoderDecoderIsacT<T>::Max10MsFramesInAPacket() const { | 133 int AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const { |
| 131 return 6; // iSAC puts at most 60 ms in a packet. | 134 return 6; // iSAC puts at most 60 ms in a packet. |
| 132 } | 135 } |
| 133 | 136 |
| 134 template <typename T> | 137 template <typename T> |
| 135 int AudioEncoderDecoderIsacT<T>::GetTargetBitrate() const { | 138 int AudioEncoderIsacT<T>::GetTargetBitrate() const { |
| 136 return target_bitrate_bps_; | 139 return target_bitrate_bps_; |
| 137 } | 140 } |
| 138 | 141 |
| 139 template <typename T> | 142 template <typename T> |
| 140 AudioEncoder::EncodedInfo AudioEncoderDecoderIsacT<T>::EncodeInternal( | 143 AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeInternal( |
| 141 uint32_t rtp_timestamp, | 144 uint32_t rtp_timestamp, |
| 142 const int16_t* audio, | 145 const int16_t* audio, |
| 143 size_t max_encoded_bytes, | 146 size_t max_encoded_bytes, |
| 144 uint8_t* encoded) { | 147 uint8_t* encoded) { |
| 145 CriticalSectionScoped cs_lock(lock_.get()); | |
| 146 if (!packet_in_progress_) { | 148 if (!packet_in_progress_) { |
| 147 // Starting a new packet; remember the timestamp for later. | 149 // Starting a new packet; remember the timestamp for later. |
| 148 packet_in_progress_ = true; | 150 packet_in_progress_ = true; |
| 149 packet_timestamp_ = rtp_timestamp; | 151 packet_timestamp_ = rtp_timestamp; |
| 150 } | 152 } |
| 151 int r; | 153 if (bwinfo_) { |
| 152 { | 154 IsacBandwidthInfo bwinfo = bwinfo_->Get(); |
| 153 CriticalSectionScoped cs(state_lock_.get()); | 155 T::SetBandwidthInfo(isac_state_, &bwinfo); |
| 154 r = T::Encode(isac_state_, audio, encoded); | |
| 155 CHECK_GE(r, 0) << "Encode failed (error code " | |
| 156 << T::GetErrorCode(isac_state_) << ")"; | |
| 157 } | 156 } |
| 157 int r = T::Encode(isac_state_, audio, encoded); | |
| 158 CHECK_GE(r, 0) << "Encode failed (error code " << T::GetErrorCode(isac_state_) | |
| 159 << ")"; | |
| 158 | 160 |
| 159 // T::Encode doesn't allow us to tell it the size of the output | 161 // T::Encode doesn't allow us to tell it the size of the output |
| 160 // buffer. All we can do is check for an overrun after the fact. | 162 // buffer. All we can do is check for an overrun after the fact. |
| 161 CHECK(static_cast<size_t>(r) <= max_encoded_bytes); | 163 CHECK_LE(static_cast<size_t>(r), max_encoded_bytes); |
| 162 | 164 |
| 163 if (r == 0) | 165 if (r == 0) |
| 164 return EncodedInfo(); | 166 return EncodedInfo(); |
| 165 | 167 |
| 166 // Got enough input to produce a packet. Return the saved timestamp from | 168 // Got enough input to produce a packet. Return the saved timestamp from |
| 167 // the first chunk of input that went into the packet. | 169 // the first chunk of input that went into the packet. |
| 168 packet_in_progress_ = false; | 170 packet_in_progress_ = false; |
| 169 EncodedInfo info; | 171 EncodedInfo info; |
| 170 info.encoded_bytes = r; | 172 info.encoded_bytes = r; |
| 171 info.encoded_timestamp = packet_timestamp_; | 173 info.encoded_timestamp = packet_timestamp_; |
| 172 info.payload_type = payload_type_; | 174 info.payload_type = payload_type_; |
| 173 return info; | 175 return info; |
| 174 } | 176 } |
| 175 | 177 |
| 176 template <typename T> | 178 template <typename T> |
| 177 int AudioEncoderDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded, | 179 AudioDecoderIsacT<T>::AudioDecoderIsacT() |
| 178 size_t encoded_len, | 180 : AudioDecoderIsacT(nullptr) { |
| 179 int sample_rate_hz, | 181 } |
| 180 int16_t* decoded, | 182 |
| 181 SpeechType* speech_type) { | 183 template <typename T> |
| 182 CriticalSectionScoped cs(state_lock_.get()); | 184 AudioDecoderIsacT<T>::AudioDecoderIsacT(LockedIsacBandwidthInfo* bwinfo) |
| 185 : bwinfo_(bwinfo), decoder_sample_rate_hz_(-1) { | |
| 186 CHECK_EQ(0, T::Create(&isac_state_)); | |
| 187 CHECK_EQ(0, T::DecoderInit(isac_state_)); | |
| 188 if (bwinfo_) { | |
| 189 IsacBandwidthInfo bwinfo; | |
|
brucedawson
2015/08/26 18:45:57
This variable shadows the function parameter bwinf
kwiberg-webrtc
2015/08/27 09:01:48
Good idea. CL here: https://codereview.webrtc.org/
| |
| 190 T::GetBandwidthInfo(isac_state_, &bwinfo); | |
| 191 bwinfo_->Set(bwinfo); | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 template <typename T> | |
| 196 AudioDecoderIsacT<T>::~AudioDecoderIsacT() { | |
| 197 CHECK_EQ(0, T::Free(isac_state_)); | |
| 198 } | |
| 199 | |
| 200 template <typename T> | |
| 201 int AudioDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded, | |
| 202 size_t encoded_len, | |
| 203 int sample_rate_hz, | |
| 204 int16_t* decoded, | |
| 205 SpeechType* speech_type) { | |
| 183 // We want to crate the illusion that iSAC supports 48000 Hz decoding, while | 206 // We want to crate the illusion that iSAC supports 48000 Hz decoding, while |
| 184 // in fact it outputs 32000 Hz. This is the iSAC fullband mode. | 207 // in fact it outputs 32000 Hz. This is the iSAC fullband mode. |
| 185 if (sample_rate_hz == 48000) | 208 if (sample_rate_hz == 48000) |
| 186 sample_rate_hz = 32000; | 209 sample_rate_hz = 32000; |
| 187 CHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000) | 210 CHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000) |
| 188 << "Unsupported sample rate " << sample_rate_hz; | 211 << "Unsupported sample rate " << sample_rate_hz; |
| 189 if (sample_rate_hz != decoder_sample_rate_hz_) { | 212 if (sample_rate_hz != decoder_sample_rate_hz_) { |
| 190 CHECK_EQ(0, T::SetDecSampRate(isac_state_, sample_rate_hz)); | 213 CHECK_EQ(0, T::SetDecSampRate(isac_state_, sample_rate_hz)); |
| 191 decoder_sample_rate_hz_ = sample_rate_hz; | 214 decoder_sample_rate_hz_ = sample_rate_hz; |
| 192 } | 215 } |
| 193 int16_t temp_type = 1; // Default is speech. | 216 int16_t temp_type = 1; // Default is speech. |
| 194 int ret = | 217 int ret = |
| 195 T::DecodeInternal(isac_state_, encoded, static_cast<int16_t>(encoded_len), | 218 T::DecodeInternal(isac_state_, encoded, static_cast<int16_t>(encoded_len), |
| 196 decoded, &temp_type); | 219 decoded, &temp_type); |
| 197 *speech_type = ConvertSpeechType(temp_type); | 220 *speech_type = ConvertSpeechType(temp_type); |
| 198 return ret; | 221 return ret; |
| 199 } | 222 } |
| 200 | 223 |
| 201 template <typename T> | 224 template <typename T> |
| 202 bool AudioEncoderDecoderIsacT<T>::HasDecodePlc() const { | 225 bool AudioDecoderIsacT<T>::HasDecodePlc() const { |
| 203 return false; | 226 return false; |
| 204 } | 227 } |
| 205 | 228 |
| 206 template <typename T> | 229 template <typename T> |
| 207 int AudioEncoderDecoderIsacT<T>::DecodePlc(int num_frames, int16_t* decoded) { | 230 int AudioDecoderIsacT<T>::DecodePlc(int num_frames, int16_t* decoded) { |
| 208 CriticalSectionScoped cs(state_lock_.get()); | |
| 209 return T::DecodePlc(isac_state_, decoded, num_frames); | 231 return T::DecodePlc(isac_state_, decoded, num_frames); |
| 210 } | 232 } |
| 211 | 233 |
| 212 template <typename T> | 234 template <typename T> |
| 213 int AudioEncoderDecoderIsacT<T>::Init() { | 235 int AudioDecoderIsacT<T>::Init() { |
| 214 CriticalSectionScoped cs(state_lock_.get()); | |
| 215 return T::DecoderInit(isac_state_); | 236 return T::DecoderInit(isac_state_); |
| 216 } | 237 } |
| 217 | 238 |
| 218 template <typename T> | 239 template <typename T> |
| 219 int AudioEncoderDecoderIsacT<T>::IncomingPacket(const uint8_t* payload, | 240 int AudioDecoderIsacT<T>::IncomingPacket(const uint8_t* payload, |
| 220 size_t payload_len, | 241 size_t payload_len, |
| 221 uint16_t rtp_sequence_number, | 242 uint16_t rtp_sequence_number, |
| 222 uint32_t rtp_timestamp, | 243 uint32_t rtp_timestamp, |
| 223 uint32_t arrival_timestamp) { | 244 uint32_t arrival_timestamp) { |
| 224 CriticalSectionScoped cs(state_lock_.get()); | 245 int ret = T::UpdateBwEstimate( |
| 225 return T::UpdateBwEstimate( | |
| 226 isac_state_, payload, static_cast<int32_t>(payload_len), | 246 isac_state_, payload, static_cast<int32_t>(payload_len), |
| 227 rtp_sequence_number, rtp_timestamp, arrival_timestamp); | 247 rtp_sequence_number, rtp_timestamp, arrival_timestamp); |
| 248 if (bwinfo_) { | |
| 249 IsacBandwidthInfo bwinfo; | |
| 250 T::GetBandwidthInfo(isac_state_, &bwinfo); | |
| 251 bwinfo_->Set(bwinfo); | |
| 252 } | |
| 253 return ret; | |
| 228 } | 254 } |
| 229 | 255 |
| 230 template <typename T> | 256 template <typename T> |
| 231 int AudioEncoderDecoderIsacT<T>::ErrorCode() { | 257 int AudioDecoderIsacT<T>::ErrorCode() { |
| 232 CriticalSectionScoped cs(state_lock_.get()); | |
| 233 return T::GetErrorCode(isac_state_); | 258 return T::GetErrorCode(isac_state_); |
| 234 } | 259 } |
| 235 | 260 |
| 261 template <typename T> | |
| 262 size_t AudioDecoderIsacT<T>::Channels() const { | |
| 263 return 1; | |
| 264 } | |
| 265 | |
| 236 } // namespace webrtc | 266 } // namespace webrtc |
| 237 | 267 |
| 238 #endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_ | 268 #endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_ |
| OLD | NEW |