Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h

Issue 1208993010: iSAC: Make separate AudioEncoder and AudioDecoder objects (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: review fixes Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698