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 |