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 |
(...skipping 11 matching lines...) Expand all Loading... | |
22 namespace { | 22 namespace { |
23 | 23 |
24 const int kSampleRateHz = 48000; | 24 const int kSampleRateHz = 48000; |
25 const int kMinBitrateBps = 500; | 25 const int kMinBitrateBps = 500; |
26 const int kMaxBitrateBps = 512000; | 26 const int kMaxBitrateBps = 512000; |
27 | 27 |
28 AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) { | 28 AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) { |
29 AudioEncoderOpus::Config config; | 29 AudioEncoderOpus::Config config; |
30 config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48); | 30 config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48); |
31 config.num_channels = codec_inst.channels; | 31 config.num_channels = codec_inst.channels; |
32 config.bitrate_bps = codec_inst.rate; | 32 config.bitrate_bps = rtc::Optional<int>(codec_inst.rate); |
33 config.payload_type = codec_inst.pltype; | 33 config.payload_type = codec_inst.pltype; |
34 config.application = config.num_channels == 1 ? AudioEncoderOpus::kVoip | 34 config.application = config.num_channels == 1 ? AudioEncoderOpus::kVoip |
35 : AudioEncoderOpus::kAudio; | 35 : AudioEncoderOpus::kAudio; |
36 return config; | 36 return config; |
37 } | 37 } |
38 | 38 |
39 // Optimize the loss rate to configure Opus. Basically, optimized loss rate is | 39 // Optimize the loss rate to configure Opus. Basically, optimized loss rate is |
40 // the input loss rate rounded down to various levels, because a robustly good | 40 // the input loss rate rounded down to various levels, because a robustly good |
41 // audio quality is achieved by lowering the packet loss down. | 41 // audio quality is achieved by lowering the packet loss down. |
42 // Additionally, to prevent toggling, margins are used, i.e., when jumping to | 42 // Additionally, to prevent toggling, margins are used, i.e., when jumping to |
(...skipping 28 matching lines...) Expand all Loading... | |
71 return kPacketLossRate5; | 71 return kPacketLossRate5; |
72 } else if (new_loss_rate >= kPacketLossRate1) { | 72 } else if (new_loss_rate >= kPacketLossRate1) { |
73 return kPacketLossRate1; | 73 return kPacketLossRate1; |
74 } else { | 74 } else { |
75 return 0.0; | 75 return 0.0; |
76 } | 76 } |
77 } | 77 } |
78 | 78 |
79 } // namespace | 79 } // namespace |
80 | 80 |
81 AudioEncoderOpus::Config::Config() = default; | |
82 AudioEncoderOpus::Config::Config(const Config&) = default; | |
83 AudioEncoderOpus::Config::~Config() = default; | |
84 auto AudioEncoderOpus::Config::operator=(const Config&) -> Config& = default; | |
hlundin-webrtc
2016/05/18 00:34:47
I don't understand this syntax. Please, educate me
kwiberg-webrtc
2016/05/18 02:54:28
It's a trailing return type (see http://en.cpprefe
| |
85 | |
81 bool AudioEncoderOpus::Config::IsOk() const { | 86 bool AudioEncoderOpus::Config::IsOk() const { |
82 if (frame_size_ms <= 0 || frame_size_ms % 10 != 0) | 87 if (frame_size_ms <= 0 || frame_size_ms % 10 != 0) |
83 return false; | 88 return false; |
84 if (num_channels != 1 && num_channels != 2) | 89 if (num_channels != 1 && num_channels != 2) |
85 return false; | 90 return false; |
86 if (bitrate_bps < kMinBitrateBps || bitrate_bps > kMaxBitrateBps) | 91 if (bitrate_bps && |
92 (*bitrate_bps < kMinBitrateBps || *bitrate_bps > kMaxBitrateBps)) | |
87 return false; | 93 return false; |
88 if (complexity < 0 || complexity > 10) | 94 if (complexity < 0 || complexity > 10) |
89 return false; | 95 return false; |
90 return true; | 96 return true; |
91 } | 97 } |
92 | 98 |
99 int AudioEncoderOpus::Config::GetBitrateBps() const { | |
100 RTC_DCHECK(IsOk()); | |
101 if (bitrate_bps) | |
102 return *bitrate_bps; // Explicitly set value. | |
103 else | |
104 return num_channels == 1 ? 32000 : 64000; // Default value. | |
105 } | |
106 | |
93 AudioEncoderOpus::AudioEncoderOpus(const Config& config) | 107 AudioEncoderOpus::AudioEncoderOpus(const Config& config) |
94 : packet_loss_rate_(0.0), inst_(nullptr) { | 108 : packet_loss_rate_(0.0), inst_(nullptr) { |
95 RTC_CHECK(RecreateEncoderInstance(config)); | 109 RTC_CHECK(RecreateEncoderInstance(config)); |
96 } | 110 } |
97 | 111 |
98 AudioEncoderOpus::AudioEncoderOpus(const CodecInst& codec_inst) | 112 AudioEncoderOpus::AudioEncoderOpus(const CodecInst& codec_inst) |
99 : AudioEncoderOpus(CreateConfig(codec_inst)) {} | 113 : AudioEncoderOpus(CreateConfig(codec_inst)) {} |
100 | 114 |
101 AudioEncoderOpus::~AudioEncoderOpus() { | 115 AudioEncoderOpus::~AudioEncoderOpus() { |
102 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_)); | 116 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_)); |
103 } | 117 } |
104 | 118 |
105 int AudioEncoderOpus::SampleRateHz() const { | 119 int AudioEncoderOpus::SampleRateHz() const { |
106 return kSampleRateHz; | 120 return kSampleRateHz; |
107 } | 121 } |
108 | 122 |
109 size_t AudioEncoderOpus::NumChannels() const { | 123 size_t AudioEncoderOpus::NumChannels() const { |
110 return config_.num_channels; | 124 return config_.num_channels; |
111 } | 125 } |
112 | 126 |
113 size_t AudioEncoderOpus::Num10MsFramesInNextPacket() const { | 127 size_t AudioEncoderOpus::Num10MsFramesInNextPacket() const { |
114 return Num10msFramesPerPacket(); | 128 return Num10msFramesPerPacket(); |
115 } | 129 } |
116 | 130 |
117 size_t AudioEncoderOpus::Max10MsFramesInAPacket() const { | 131 size_t AudioEncoderOpus::Max10MsFramesInAPacket() const { |
118 return Num10msFramesPerPacket(); | 132 return Num10msFramesPerPacket(); |
119 } | 133 } |
120 | 134 |
121 int AudioEncoderOpus::GetTargetBitrate() const { | 135 int AudioEncoderOpus::GetTargetBitrate() const { |
122 return config_.bitrate_bps; | 136 return config_.GetBitrateBps(); |
123 } | 137 } |
124 | 138 |
125 void AudioEncoderOpus::Reset() { | 139 void AudioEncoderOpus::Reset() { |
126 RTC_CHECK(RecreateEncoderInstance(config_)); | 140 RTC_CHECK(RecreateEncoderInstance(config_)); |
127 } | 141 } |
128 | 142 |
129 bool AudioEncoderOpus::SetFec(bool enable) { | 143 bool AudioEncoderOpus::SetFec(bool enable) { |
130 auto conf = config_; | 144 auto conf = config_; |
131 conf.fec_enabled = enable; | 145 conf.fec_enabled = enable; |
132 return RecreateEncoderInstance(conf); | 146 return RecreateEncoderInstance(conf); |
(...skipping 28 matching lines...) Expand all Loading... | |
161 double opt_loss_rate = OptimizePacketLossRate(fraction, packet_loss_rate_); | 175 double opt_loss_rate = OptimizePacketLossRate(fraction, packet_loss_rate_); |
162 if (packet_loss_rate_ != opt_loss_rate) { | 176 if (packet_loss_rate_ != opt_loss_rate) { |
163 packet_loss_rate_ = opt_loss_rate; | 177 packet_loss_rate_ = opt_loss_rate; |
164 RTC_CHECK_EQ( | 178 RTC_CHECK_EQ( |
165 0, WebRtcOpus_SetPacketLossRate( | 179 0, WebRtcOpus_SetPacketLossRate( |
166 inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5))); | 180 inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5))); |
167 } | 181 } |
168 } | 182 } |
169 | 183 |
170 void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) { | 184 void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) { |
171 config_.bitrate_bps = | 185 config_.bitrate_bps = rtc::Optional<int>( |
172 std::max(std::min(bits_per_second, kMaxBitrateBps), kMinBitrateBps); | 186 std::max(std::min(bits_per_second, kMaxBitrateBps), kMinBitrateBps)); |
173 RTC_DCHECK(config_.IsOk()); | 187 RTC_DCHECK(config_.IsOk()); |
174 RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config_.bitrate_bps)); | 188 RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config_.GetBitrateBps())); |
175 } | 189 } |
176 | 190 |
177 AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl( | 191 AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl( |
178 uint32_t rtp_timestamp, | 192 uint32_t rtp_timestamp, |
179 rtc::ArrayView<const int16_t> audio, | 193 rtc::ArrayView<const int16_t> audio, |
180 rtc::Buffer* encoded) { | 194 rtc::Buffer* encoded) { |
181 | 195 |
182 if (input_buffer_.empty()) | 196 if (input_buffer_.empty()) |
183 first_timestamp_in_buffer_ = rtp_timestamp; | 197 first_timestamp_in_buffer_ = rtp_timestamp; |
184 | 198 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
221 } | 235 } |
222 | 236 |
223 size_t AudioEncoderOpus::SamplesPer10msFrame() const { | 237 size_t AudioEncoderOpus::SamplesPer10msFrame() const { |
224 return rtc::CheckedDivExact(kSampleRateHz, 100) * config_.num_channels; | 238 return rtc::CheckedDivExact(kSampleRateHz, 100) * config_.num_channels; |
225 } | 239 } |
226 | 240 |
227 size_t AudioEncoderOpus::SufficientOutputBufferSize() const { | 241 size_t AudioEncoderOpus::SufficientOutputBufferSize() const { |
228 // Calculate the number of bytes we expect the encoder to produce, | 242 // Calculate the number of bytes we expect the encoder to produce, |
229 // then multiply by two to give a wide margin for error. | 243 // then multiply by two to give a wide margin for error. |
230 const size_t bytes_per_millisecond = | 244 const size_t bytes_per_millisecond = |
231 static_cast<size_t>(config_.bitrate_bps / (1000 * 8) + 1); | 245 static_cast<size_t>(config_.GetBitrateBps() / (1000 * 8) + 1); |
232 const size_t approx_encoded_bytes = | 246 const size_t approx_encoded_bytes = |
233 Num10msFramesPerPacket() * 10 * bytes_per_millisecond; | 247 Num10msFramesPerPacket() * 10 * bytes_per_millisecond; |
234 return 2 * approx_encoded_bytes; | 248 return 2 * approx_encoded_bytes; |
235 } | 249 } |
236 | 250 |
237 // If the given config is OK, recreate the Opus encoder instance with those | 251 // If the given config is OK, recreate the Opus encoder instance with those |
238 // settings, save the config, and return true. Otherwise, do nothing and return | 252 // settings, save the config, and return true. Otherwise, do nothing and return |
239 // false. | 253 // false. |
240 bool AudioEncoderOpus::RecreateEncoderInstance(const Config& config) { | 254 bool AudioEncoderOpus::RecreateEncoderInstance(const Config& config) { |
241 if (!config.IsOk()) | 255 if (!config.IsOk()) |
242 return false; | 256 return false; |
243 if (inst_) | 257 if (inst_) |
244 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_)); | 258 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_)); |
245 input_buffer_.clear(); | 259 input_buffer_.clear(); |
246 input_buffer_.reserve(Num10msFramesPerPacket() * SamplesPer10msFrame()); | 260 input_buffer_.reserve(Num10msFramesPerPacket() * SamplesPer10msFrame()); |
247 RTC_CHECK_EQ(0, WebRtcOpus_EncoderCreate(&inst_, config.num_channels, | 261 RTC_CHECK_EQ(0, WebRtcOpus_EncoderCreate(&inst_, config.num_channels, |
248 config.application)); | 262 config.application)); |
249 RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config.bitrate_bps)); | 263 RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config.GetBitrateBps())); |
250 if (config.fec_enabled) { | 264 if (config.fec_enabled) { |
251 RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_)); | 265 RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_)); |
252 } else { | 266 } else { |
253 RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_)); | 267 RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_)); |
254 } | 268 } |
255 RTC_CHECK_EQ( | 269 RTC_CHECK_EQ( |
256 0, WebRtcOpus_SetMaxPlaybackRate(inst_, config.max_playback_rate_hz)); | 270 0, WebRtcOpus_SetMaxPlaybackRate(inst_, config.max_playback_rate_hz)); |
257 RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, config.complexity)); | 271 RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, config.complexity)); |
258 if (config.dtx_enabled) { | 272 if (config.dtx_enabled) { |
259 RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_)); | 273 RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_)); |
260 } else { | 274 } else { |
261 RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_)); | 275 RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_)); |
262 } | 276 } |
263 RTC_CHECK_EQ(0, | 277 RTC_CHECK_EQ(0, |
264 WebRtcOpus_SetPacketLossRate( | 278 WebRtcOpus_SetPacketLossRate( |
265 inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5))); | 279 inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5))); |
266 config_ = config; | 280 config_ = config; |
267 return true; | 281 return true; |
268 } | 282 } |
269 | 283 |
270 } // namespace webrtc | 284 } // namespace webrtc |
OLD | NEW |