1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/codec/audio_encoder_opus.h"
8 #include "base/logging.h"
9 #include "base/time/time.h"
10 #include "media/base/audio_bus.h"
11 #include "media/base/multi_channel_resampler.h"
12 #include "third_party/opus/src/include/opus.h"
18 // Output 160 kb/s bitrate.
19 const int kOutputBitrateBps
= 160 * 1024;
21 // Opus doesn't support 44100 sampling rate so we always resample to 48kHz.
22 const AudioPacket::SamplingRate kOpusSamplingRate
=
23 AudioPacket::SAMPLING_RATE_48000
;
25 // Opus supports frame sizes of 2.5, 5, 10, 20, 40 and 60 ms. We use 20 ms
26 // frames to balance latency and efficiency.
27 const int kFrameSizeMs
= 20;
29 // Number of samples per frame when using default sampling rate.
30 const int kFrameSamples
=
31 kOpusSamplingRate
* kFrameSizeMs
/ base::Time::kMillisecondsPerSecond
;
33 const AudioPacket::BytesPerSample kBytesPerSample
=
34 AudioPacket::BYTES_PER_SAMPLE_2
;
36 bool IsSupportedSampleRate(int rate
) {
37 return rate
== 44100 || rate
== 48000;
42 AudioEncoderOpus::AudioEncoderOpus()
44 channels_(AudioPacket::CHANNELS_STEREO
),
47 resampling_data_(NULL
),
48 resampling_data_size_(0),
49 resampling_data_pos_(0) {
52 AudioEncoderOpus::~AudioEncoderOpus() {
56 void AudioEncoderOpus::InitEncoder() {
59 encoder_
= opus_encoder_create(kOpusSamplingRate
, channels_
,
60 OPUS_APPLICATION_AUDIO
, &error
);
62 LOG(ERROR
) << "Failed to create OPUS encoder. Error code: " << error
;
66 opus_encoder_ctl(encoder_
, OPUS_SET_BITRATE(kOutputBitrateBps
));
68 frame_size_
= sampling_rate_
* kFrameSizeMs
/
69 base::Time::kMillisecondsPerSecond
;
71 if (sampling_rate_
!= kOpusSamplingRate
) {
72 resample_buffer_
.reset(
73 new char[kFrameSamples
* kBytesPerSample
* channels_
]);
74 // TODO(sergeyu): Figure out the right buffer size to use per packet instead
75 // of using media::SincResampler::kDefaultRequestSize.
76 resampler_
.reset(new media::MultiChannelResampler(
78 static_cast<double>(sampling_rate_
) / kOpusSamplingRate
,
79 media::SincResampler::kDefaultRequestSize
,
80 base::Bind(&AudioEncoderOpus::FetchBytesToResample
,
81 base::Unretained(this))));
82 resampler_bus_
= media::AudioBus::Create(channels_
, kFrameSamples
);
85 // Drop leftover data because it's for different sampling rate.
86 leftover_samples_
= 0;
87 leftover_buffer_size_
=
88 frame_size_
+ media::SincResampler::kDefaultRequestSize
;
89 leftover_buffer_
.reset(
90 new int16
[leftover_buffer_size_
* channels_
]);
93 void AudioEncoderOpus::DestroyEncoder() {
95 opus_encoder_destroy(encoder_
);
102 bool AudioEncoderOpus::ResetForPacket(AudioPacket
* packet
) {
103 if (packet
->channels() != channels_
||
104 packet
->sampling_rate() != sampling_rate_
) {
107 channels_
= packet
->channels();
108 sampling_rate_
= packet
->sampling_rate();
110 if (channels_
<= 0 || channels_
> 2 ||
111 !IsSupportedSampleRate(sampling_rate_
)) {
112 LOG(WARNING
) << "Unsupported OPUS parameters: "
113 << channels_
<< " channels with "
114 << sampling_rate_
<< " samples per second.";
121 return encoder_
!= NULL
;
124 void AudioEncoderOpus::FetchBytesToResample(int resampler_frame_delay
,
125 media::AudioBus
* audio_bus
) {
126 DCHECK(resampling_data_
);
127 int samples_left
= (resampling_data_size_
- resampling_data_pos_
) /
128 kBytesPerSample
/ channels_
;
129 DCHECK_LE(audio_bus
->frames(), samples_left
);
130 audio_bus
->FromInterleaved(
131 resampling_data_
+ resampling_data_pos_
,
132 audio_bus
->frames(), kBytesPerSample
);
133 resampling_data_pos_
+= audio_bus
->frames() * kBytesPerSample
* channels_
;
134 DCHECK_LE(resampling_data_pos_
, static_cast<int>(resampling_data_size_
));
137 scoped_ptr
<AudioPacket
> AudioEncoderOpus::Encode(
138 scoped_ptr
<AudioPacket
> packet
) {
139 DCHECK_EQ(AudioPacket::ENCODING_RAW
, packet
->encoding());
140 DCHECK_EQ(1, packet
->data_size());
141 DCHECK_EQ(kBytesPerSample
, packet
->bytes_per_sample());
143 if (!ResetForPacket(packet
.get())) {
144 LOG(ERROR
) << "Encoder initialization failed";
148 int samples_in_packet
= packet
->data(0).size() / kBytesPerSample
/ channels_
;
149 const int16
* next_sample
=
150 reinterpret_cast<const int16
*>(packet
->data(0).data());
152 // Create a new packet of encoded data.
153 scoped_ptr
<AudioPacket
> encoded_packet(new AudioPacket());
154 encoded_packet
->set_encoding(AudioPacket::ENCODING_OPUS
);
155 encoded_packet
->set_sampling_rate(kOpusSamplingRate
);
156 encoded_packet
->set_channels(channels_
);
158 int prefetch_samples
=
159 resampler_
.get() ? media::SincResampler::kDefaultRequestSize
: 0;
160 int samples_wanted
= frame_size_
+ prefetch_samples
;
162 while (leftover_samples_
+ samples_in_packet
>= samples_wanted
) {
163 const int16
* pcm_buffer
= NULL
;
165 // Combine the packet with the leftover samples, if any.
166 if (leftover_samples_
> 0) {
167 pcm_buffer
= leftover_buffer_
.get();
168 int samples_to_copy
= samples_wanted
- leftover_samples_
;
169 memcpy(leftover_buffer_
.get() + leftover_samples_
* channels_
,
170 next_sample
, samples_to_copy
* kBytesPerSample
* channels_
);
172 pcm_buffer
= next_sample
;
175 // Resample data if necessary.
176 int samples_consumed
= 0;
177 if (resampler_
.get()) {
178 resampling_data_
= reinterpret_cast<const char*>(pcm_buffer
);
179 resampling_data_pos_
= 0;
180 resampling_data_size_
= samples_wanted
* channels_
* kBytesPerSample
;
181 resampler_
->Resample(kFrameSamples
, resampler_bus_
.get());
182 resampling_data_
= NULL
;
183 samples_consumed
= resampling_data_pos_
/ channels_
/ kBytesPerSample
;
185 resampler_bus_
->ToInterleaved(kFrameSamples
, kBytesPerSample
,
186 resample_buffer_
.get());
187 pcm_buffer
= reinterpret_cast<int16
*>(resample_buffer_
.get());
189 samples_consumed
= frame_size_
;
192 // Initialize output buffer.
193 std::string
* data
= encoded_packet
->add_data();
194 data
->resize(kFrameSamples
* kBytesPerSample
* channels_
);
197 unsigned char* buffer
=
198 reinterpret_cast<unsigned char*>(string_as_array(data
));
199 int result
= opus_encode(encoder_
, pcm_buffer
, kFrameSamples
,
200 buffer
, data
->length());
202 LOG(ERROR
) << "opus_encode() failed with error code: " << result
;
206 DCHECK_LE(result
, static_cast<int>(data
->length()));
207 data
->resize(result
);
209 // Cleanup leftover buffer.
210 if (samples_consumed
>= leftover_samples_
) {
211 samples_consumed
-= leftover_samples_
;
212 leftover_samples_
= 0;
213 next_sample
+= samples_consumed
* channels_
;
214 samples_in_packet
-= samples_consumed
;
216 leftover_samples_
-= samples_consumed
;
217 memmove(leftover_buffer_
.get(),
218 leftover_buffer_
.get() + samples_consumed
* channels_
,
219 leftover_samples_
* channels_
* kBytesPerSample
);
223 // Store the leftover samples.
224 if (samples_in_packet
> 0) {
225 DCHECK_LE(leftover_samples_
+ samples_in_packet
, leftover_buffer_size_
);
226 memmove(leftover_buffer_
.get() + leftover_samples_
* channels_
,
227 next_sample
, samples_in_packet
* kBytesPerSample
* channels_
);
228 leftover_samples_
+= samples_in_packet
;
231 // Return NULL if there's nothing in the packet.
232 if (encoded_packet
->data_size() == 0)
235 return encoded_packet
.Pass();
238 } // namespace remoting