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 |