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 | 20 |
| 21 namespace webrtc { | 21 namespace webrtc { |
| 22 | 22 |
| 23 const int kIsacPayloadType = 103; | 23 template <typename T> |
| 24 const int kDefaultBitRate = 32000; | 24 typename AudioEncoderIsacT<T>::Config CreateIsacConfig( |
| 25 const CodecInst& codec_inst, | |
| 26 LockedIsacBandwidthInfo* bwinfo) { | |
| 27 typename AudioEncoderIsacT<T>::Config config; | |
| 28 config.bwinfo = bwinfo; | |
| 29 config.payload_type = codec_inst.pltype; | |
| 30 config.sample_rate_hz = codec_inst.plfreq; | |
| 31 config.frame_size_ms = | |
| 32 rtc::CheckedDivExact(1000 * codec_inst.pacsize, config.sample_rate_hz); | |
| 33 config.adaptive_mode = (codec_inst.rate == -1); | |
| 34 if (codec_inst.rate != -1) | |
| 35 config.bit_rate = codec_inst.rate; | |
| 36 return config; | |
| 37 } | |
| 25 | 38 |
| 26 template <typename T> | 39 template <typename T> |
| 27 AudioEncoderIsacT<T>::Config::Config() | 40 AudioEncoderIsacT<T>::Config::Config() = default; |
| 28 : bwinfo(nullptr), | |
| 29 payload_type(kIsacPayloadType), | |
| 30 sample_rate_hz(16000), | |
| 31 frame_size_ms(30), | |
| 32 bit_rate(kDefaultBitRate), | |
| 33 max_payload_size_bytes(-1), | |
| 34 max_bit_rate(-1), | |
| 35 adaptive_mode(false), | |
| 36 enforce_frame_size(false) { | |
| 37 } | |
| 38 | 41 |
| 39 template <typename T> | 42 template <typename T> |
| 40 bool AudioEncoderIsacT<T>::Config::IsOk() const { | 43 bool AudioEncoderIsacT<T>::Config::IsOk() const { |
| 41 if (max_bit_rate < 32000 && max_bit_rate != -1) | 44 if (max_bit_rate < 32000 && max_bit_rate != -1) |
| 42 return false; | 45 return false; |
| 43 if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1) | 46 if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1) |
| 44 return false; | 47 return false; |
| 45 if (adaptive_mode && !bwinfo) | 48 if (adaptive_mode && !bwinfo) |
| 46 return false; | 49 return false; |
| 47 switch (sample_rate_hz) { | 50 switch (sample_rate_hz) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 60 return false; | 63 return false; |
| 61 return T::has_swb && | 64 return T::has_swb && |
| 62 (frame_size_ms == 30 && | 65 (frame_size_ms == 30 && |
| 63 (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 56000))); | 66 (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 56000))); |
| 64 default: | 67 default: |
| 65 return false; | 68 return false; |
| 66 } | 69 } |
| 67 } | 70 } |
| 68 | 71 |
| 69 template <typename T> | 72 template <typename T> |
| 70 AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config) | 73 AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config) { |
| 71 : payload_type_(config.payload_type), | 74 RecreateEncoderInstance(config); |
| 72 bwinfo_(config.bwinfo), | 75 } |
| 73 packet_in_progress_(false), | |
| 74 target_bitrate_bps_(config.adaptive_mode ? -1 : (config.bit_rate == 0 | |
| 75 ? kDefaultBitRate | |
| 76 : config.bit_rate)) { | |
| 77 CHECK(config.IsOk()); | |
| 78 CHECK_EQ(0, T::Create(&isac_state_)); | |
| 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)); | |
| 81 const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate; | |
| 82 if (config.adaptive_mode) { | |
| 83 CHECK_EQ(0, T::ControlBwe(isac_state_, bit_rate, config.frame_size_ms, | |
| 84 config.enforce_frame_size)); | |
| 85 } else { | |
| 86 CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms)); | |
| 87 } | |
| 88 if (config.max_payload_size_bytes != -1) | |
| 89 CHECK_EQ(0, | |
| 90 T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes)); | |
| 91 if (config.max_bit_rate != -1) | |
| 92 CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate)); | |
| 93 | 76 |
| 94 // When config.sample_rate_hz is set to 48000 Hz (iSAC-fb), the decoder is | 77 template <typename T> |
| 95 // still set to 32000 Hz, since there is no full-band mode in the decoder. | 78 AudioEncoderIsacT<T>::AudioEncoderIsacT(const CodecInst& codec_inst, |
| 96 const int decoder_sample_rate_hz = std::min(config.sample_rate_hz, 32000); | 79 LockedIsacBandwidthInfo* bwinfo) |
| 97 | 80 : AudioEncoderIsacT(CreateIsacConfig<T>(codec_inst, bwinfo)) {} |
| 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)); | |
| 103 } | |
| 104 | 81 |
| 105 template <typename T> | 82 template <typename T> |
| 106 AudioEncoderIsacT<T>::~AudioEncoderIsacT() { | 83 AudioEncoderIsacT<T>::~AudioEncoderIsacT() { |
| 107 CHECK_EQ(0, T::Free(isac_state_)); | 84 CHECK_EQ(0, T::Free(isac_state_)); |
| 108 } | 85 } |
| 109 | 86 |
| 110 template <typename T> | 87 template <typename T> |
| 88 size_t AudioEncoderIsacT<T>::MaxEncodedBytes() const { | |
| 89 return kSufficientEncodeBufferSizeBytes; | |
| 90 } | |
| 91 | |
| 92 template <typename T> | |
| 111 int AudioEncoderIsacT<T>::SampleRateHz() const { | 93 int AudioEncoderIsacT<T>::SampleRateHz() const { |
| 112 return T::EncSampRate(isac_state_); | 94 return T::EncSampRate(isac_state_); |
| 113 } | 95 } |
| 114 | 96 |
| 115 template <typename T> | 97 template <typename T> |
| 116 int AudioEncoderIsacT<T>::NumChannels() const { | 98 int AudioEncoderIsacT<T>::NumChannels() const { |
| 117 return 1; | 99 return 1; |
| 118 } | 100 } |
| 119 | 101 |
| 120 template <typename T> | 102 template <typename T> |
| 121 size_t AudioEncoderIsacT<T>::MaxEncodedBytes() const { | |
| 122 return kSufficientEncodeBufferSizeBytes; | |
| 123 } | |
| 124 | |
| 125 template <typename T> | |
| 126 size_t AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const { | 103 size_t AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const { |
| 127 const int samples_in_next_packet = T::GetNewFrameLen(isac_state_); | 104 const int samples_in_next_packet = T::GetNewFrameLen(isac_state_); |
| 128 return static_cast<size_t>( | 105 return static_cast<size_t>( |
| 129 rtc::CheckedDivExact(samples_in_next_packet, | 106 rtc::CheckedDivExact(samples_in_next_packet, |
| 130 rtc::CheckedDivExact(SampleRateHz(), 100))); | 107 rtc::CheckedDivExact(SampleRateHz(), 100))); |
| 131 } | 108 } |
| 132 | 109 |
| 133 template <typename T> | 110 template <typename T> |
| 134 size_t AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const { | 111 size_t AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const { |
| 135 return 6; // iSAC puts at most 60 ms in a packet. | 112 return 6; // iSAC puts at most 60 ms in a packet. |
| 136 } | 113 } |
| 137 | 114 |
| 138 template <typename T> | 115 template <typename T> |
| 139 int AudioEncoderIsacT<T>::GetTargetBitrate() const { | 116 int AudioEncoderIsacT<T>::GetTargetBitrate() const { |
| 140 return target_bitrate_bps_; | 117 if (config_.adaptive_mode) |
| 118 return -1; | |
| 119 return config_.bit_rate == 0 ? kDefaultBitRate : config_.bit_rate; | |
| 141 } | 120 } |
| 142 | 121 |
| 143 template <typename T> | 122 template <typename T> |
| 144 AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeInternal( | 123 AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeInternal( |
| 145 uint32_t rtp_timestamp, | 124 uint32_t rtp_timestamp, |
| 146 const int16_t* audio, | 125 const int16_t* audio, |
| 147 size_t max_encoded_bytes, | 126 size_t max_encoded_bytes, |
| 148 uint8_t* encoded) { | 127 uint8_t* encoded) { |
| 149 if (!packet_in_progress_) { | 128 if (!packet_in_progress_) { |
| 150 // Starting a new packet; remember the timestamp for later. | 129 // Starting a new packet; remember the timestamp for later. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 165 | 144 |
| 166 if (r == 0) | 145 if (r == 0) |
| 167 return EncodedInfo(); | 146 return EncodedInfo(); |
| 168 | 147 |
| 169 // Got enough input to produce a packet. Return the saved timestamp from | 148 // Got enough input to produce a packet. Return the saved timestamp from |
| 170 // the first chunk of input that went into the packet. | 149 // the first chunk of input that went into the packet. |
| 171 packet_in_progress_ = false; | 150 packet_in_progress_ = false; |
| 172 EncodedInfo info; | 151 EncodedInfo info; |
| 173 info.encoded_bytes = r; | 152 info.encoded_bytes = r; |
| 174 info.encoded_timestamp = packet_timestamp_; | 153 info.encoded_timestamp = packet_timestamp_; |
| 175 info.payload_type = payload_type_; | 154 info.payload_type = config_.payload_type; |
| 176 return info; | 155 return info; |
| 177 } | 156 } |
| 178 | 157 |
| 179 template <typename T> | 158 template <typename T> |
| 159 void AudioEncoderIsacT<T>::Reset() { | |
| 160 RecreateEncoderInstance(config_); | |
| 161 } | |
| 162 | |
| 163 template <typename T> | |
| 164 void AudioEncoderIsacT<T>::SetMaxPayloadSize(int max_payload_size_bytes) { | |
| 165 auto conf = config_; | |
| 166 conf.max_payload_size_bytes = max_payload_size_bytes; | |
| 167 RecreateEncoderInstance(conf); | |
| 168 } | |
| 169 | |
| 170 template <typename T> | |
| 171 void AudioEncoderIsacT<T>::SetMaxBitrate(int max_rate_bps) { | |
| 172 auto conf = config_; | |
| 173 conf.max_bit_rate = max_rate_bps; | |
| 174 RecreateEncoderInstance(conf); | |
| 175 } | |
| 176 | |
| 177 // Recreate the iSAC encoder instance with the given settings, and save them. | |
|
hlundin-webrtc
2015/09/07 20:00:01
Move comment to declaration.
kwiberg-webrtc
2015/09/08 10:47:45
Done.
| |
| 178 template <typename T> | |
| 179 void AudioEncoderIsacT<T>::RecreateEncoderInstance(const Config& config) { | |
| 180 CHECK(config.IsOk()); | |
| 181 packet_in_progress_ = false; | |
| 182 bwinfo_ = config.bwinfo; | |
| 183 if (isac_state_) | |
| 184 CHECK_EQ(0, T::Free(isac_state_)); | |
| 185 CHECK_EQ(0, T::Create(&isac_state_)); | |
| 186 CHECK_EQ(0, T::EncoderInit(isac_state_, config.adaptive_mode ? 0 : 1)); | |
| 187 CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz)); | |
| 188 const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate; | |
| 189 if (config.adaptive_mode) { | |
| 190 CHECK_EQ(0, T::ControlBwe(isac_state_, bit_rate, config.frame_size_ms, | |
| 191 config.enforce_frame_size)); | |
| 192 } else { | |
| 193 CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms)); | |
| 194 } | |
| 195 if (config.max_payload_size_bytes != -1) | |
| 196 CHECK_EQ(0, | |
| 197 T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes)); | |
| 198 if (config.max_bit_rate != -1) | |
| 199 CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate)); | |
| 200 | |
| 201 // When config.sample_rate_hz is set to 48000 Hz (iSAC-fb), the decoder is | |
| 202 // still set to 32000 Hz, since there is no full-band mode in the decoder. | |
| 203 const int decoder_sample_rate_hz = std::min(config.sample_rate_hz, 32000); | |
| 204 | |
| 205 // Set the decoder sample rate even though we just use the encoder. This | |
| 206 // doesn't appear to be necessary to produce a valid encoding, but without it | |
| 207 // we get an encoding that isn't bit-for-bit identical with what a combined | |
| 208 // encoder+decoder object produces. | |
| 209 CHECK_EQ(0, T::SetDecSampRate(isac_state_, decoder_sample_rate_hz)); | |
| 210 | |
| 211 config_ = config; | |
| 212 } | |
| 213 | |
| 214 template <typename T> | |
| 180 AudioDecoderIsacT<T>::AudioDecoderIsacT() | 215 AudioDecoderIsacT<T>::AudioDecoderIsacT() |
| 181 : AudioDecoderIsacT(nullptr) { | 216 : AudioDecoderIsacT(nullptr) {} |
| 182 } | |
| 183 | 217 |
| 184 template <typename T> | 218 template <typename T> |
| 185 AudioDecoderIsacT<T>::AudioDecoderIsacT(LockedIsacBandwidthInfo* bwinfo) | 219 AudioDecoderIsacT<T>::AudioDecoderIsacT(LockedIsacBandwidthInfo* bwinfo) |
| 186 : bwinfo_(bwinfo), decoder_sample_rate_hz_(-1) { | 220 : bwinfo_(bwinfo), decoder_sample_rate_hz_(-1) { |
| 187 CHECK_EQ(0, T::Create(&isac_state_)); | 221 CHECK_EQ(0, T::Create(&isac_state_)); |
| 188 T::DecoderInit(isac_state_); | 222 T::DecoderInit(isac_state_); |
| 189 if (bwinfo_) { | 223 if (bwinfo_) { |
| 190 IsacBandwidthInfo bi; | 224 IsacBandwidthInfo bi; |
| 191 T::GetBandwidthInfo(isac_state_, &bi); | 225 T::GetBandwidthInfo(isac_state_, &bi); |
| 192 bwinfo_->Set(bi); | 226 bwinfo_->Set(bi); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 259 } | 293 } |
| 260 | 294 |
| 261 template <typename T> | 295 template <typename T> |
| 262 size_t AudioDecoderIsacT<T>::Channels() const { | 296 size_t AudioDecoderIsacT<T>::Channels() const { |
| 263 return 1; | 297 return 1; |
| 264 } | 298 } |
| 265 | 299 |
| 266 } // namespace webrtc | 300 } // namespace webrtc |
| 267 | 301 |
| 268 #endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_ | 302 #endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_ |
| OLD | NEW |