1 // Copyright 2013 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.
4
5 #include "media/cast/audio_sender/audio_encoder.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/sys_byteorder.h"
14 #include "base/time/time.h"
15 #include "media/base/audio_bus.h"
16 #include "media/cast/cast_defines.h"
17 #include "media/cast/cast_environment.h"
18 #include "third_party/opus/src/include/opus.h"
19
20 namespace media {
21 namespace cast {
22
LogAudioEncodedEvent(CastEnvironment * const cast_environment,const base::TimeTicks & recorded_time)23 void LogAudioEncodedEvent(CastEnvironment* const cast_environment,
24 const base::TimeTicks& recorded_time) {
25 // TODO(mikhal): Resolve timestamp calculation for audio.
26 cast_environment->Logging()->InsertFrameEvent(kAudioFrameEncoded,
27 GetVideoRtpTimestamp(recorded_time), kFrameIdUnknown);
28 }
29
30 // Base class that handles the common problem of feeding one or more AudioBus'
31 // data into a 10 ms buffer and then, once the buffer is full, encoding the
32 // signal and emitting an EncodedAudioFrame via the FrameEncodedCallback.
33 //
34 // Subclasses complete the implementation by handling the actual encoding
35 // details.
36 class AudioEncoder::ImplBase {
37 public:
ImplBase(CastEnvironment * cast_environment,AudioCodec codec,int num_channels,int sampling_rate,const FrameEncodedCallback & callback)38 ImplBase(CastEnvironment* cast_environment,
39 AudioCodec codec, int num_channels, int sampling_rate,
40 const FrameEncodedCallback& callback)
41 : cast_environment_(cast_environment),
42 codec_(codec), num_channels_(num_channels),
43 samples_per_10ms_(sampling_rate / 100),
44 callback_(callback),
45 buffer_fill_end_(0),
46 frame_id_(0) {
47 CHECK_GT(num_channels_, 0);
48 CHECK_GT(samples_per_10ms_, 0);
49 CHECK_EQ(sampling_rate % 100, 0);
50 CHECK_LE(samples_per_10ms_ * num_channels_,
51 EncodedAudioFrame::kMaxNumberOfSamples);
52 }
53
~ImplBase()54 virtual ~ImplBase() {}
55
EncodeAudio(const AudioBus * audio_bus,const base::TimeTicks & recorded_time,const base::Closure & done_callback)56 void EncodeAudio(const AudioBus* audio_bus,
57 const base::TimeTicks& recorded_time,
58 const base::Closure& done_callback) {
59 int src_pos = 0;
60 while (src_pos < audio_bus->frames()) {
61 const int num_samples_to_xfer =
62 std::min(samples_per_10ms_ - buffer_fill_end_,
63 audio_bus->frames() - src_pos);
64 DCHECK_EQ(audio_bus->channels(), num_channels_);
65 TransferSamplesIntoBuffer(
66 audio_bus, src_pos, buffer_fill_end_, num_samples_to_xfer);
67 src_pos += num_samples_to_xfer;
68 buffer_fill_end_ += num_samples_to_xfer;
69
70 if (src_pos == audio_bus->frames()) {
71 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
72 done_callback);
73 // Note: |audio_bus| is now invalid..
74 }
75
76 if (buffer_fill_end_ == samples_per_10ms_) {
77 scoped_ptr<EncodedAudioFrame> audio_frame(new EncodedAudioFrame());
78 audio_frame->codec = codec_;
79 audio_frame->frame_id = frame_id_++;
80 audio_frame->samples = samples_per_10ms_;
81 if (EncodeFromFilledBuffer(&audio_frame->data)) {
82 // Compute an offset to determine the recorded time for the first
83 // audio sample in the buffer.
84 const base::TimeDelta buffer_time_offset =
85 (buffer_fill_end_ - src_pos) *
86 base::TimeDelta::FromMilliseconds(10) / samples_per_10ms_;
87 // TODO(miu): Consider batching EncodedAudioFrames so we only post a
88 // at most one task for each call to this method.
89 cast_environment_->PostTask(
90 CastEnvironment::MAIN, FROM_HERE,
91 base::Bind(callback_, base::Passed(&audio_frame),
92 recorded_time - buffer_time_offset));
93 }
94 buffer_fill_end_ = 0;
95 }
96 }
97 }
98
99 protected:
100 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus,
101 int source_offset,
102 int buffer_fill_offset,
103 int num_samples) = 0;
104 virtual bool EncodeFromFilledBuffer(std::string* out) = 0;
105
106 CastEnvironment* const cast_environment_;
107 const AudioCodec codec_;
108 const int num_channels_;
109 const int samples_per_10ms_;
110 const FrameEncodedCallback callback_;
111
112 private:
113 // In the case where a call to EncodeAudio() cannot completely fill the
114 // buffer, this points to the position at which to populate data in a later
115 // call.
116 int buffer_fill_end_;
117
118 // A counter used to label EncodedAudioFrames.
119 uint32 frame_id_;
120
121 private:
122 DISALLOW_COPY_AND_ASSIGN(ImplBase);
123 };
124
125 class AudioEncoder::OpusImpl : public AudioEncoder::ImplBase {
126 public:
OpusImpl(CastEnvironment * cast_environment,int num_channels,int sampling_rate,int bitrate,const FrameEncodedCallback & callback)127 OpusImpl(CastEnvironment* cast_environment,
128 int num_channels, int sampling_rate, int bitrate,
129 const FrameEncodedCallback& callback)
130 : ImplBase(cast_environment, kOpus, num_channels, sampling_rate,
131 callback),
132 encoder_memory_(new uint8[opus_encoder_get_size(num_channels)]),
133 opus_encoder_(reinterpret_cast<OpusEncoder*>(encoder_memory_.get())),
134 buffer_(new float[num_channels * samples_per_10ms_]) {
135 CHECK_EQ(opus_encoder_init(opus_encoder_, sampling_rate, num_channels,
136 OPUS_APPLICATION_AUDIO),
137 OPUS_OK);
138 if (bitrate <= 0) {
139 // Note: As of 2013-10-31, the encoder in "auto bitrate" mode would use a
140 // variable bitrate up to 102kbps for 2-channel, 48 kHz audio and a 10 ms
141 // frame size. The opus library authors may, of course, adjust this in
142 // later versions.
143 bitrate = OPUS_AUTO;
144 }
145 CHECK_EQ(opus_encoder_ctl(opus_encoder_, OPUS_SET_BITRATE(bitrate)),
146 OPUS_OK);
147 }
148
~OpusImpl()149 virtual ~OpusImpl() {}
150
151 private:
TransferSamplesIntoBuffer(const AudioBus * audio_bus,int source_offset,int buffer_fill_offset,int num_samples)152 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus,
153 int source_offset,
154 int buffer_fill_offset,
155 int num_samples) OVERRIDE {
156 // Opus requires channel-interleaved samples in a single array.
157 for (int ch = 0; ch < audio_bus->channels(); ++ch) {
158 const float* src = audio_bus->channel(ch) + source_offset;
159 const float* const src_end = src + num_samples;
160 float* dest = buffer_.get() + buffer_fill_offset * num_channels_ + ch;
161 for (; src < src_end; ++src, dest += num_channels_)
162 *dest = *src;
163 }
164 }
165
EncodeFromFilledBuffer(std::string * out)166 virtual bool EncodeFromFilledBuffer(std::string* out) OVERRIDE {
167 out->resize(kOpusMaxPayloadSize);
168 const opus_int32 result = opus_encode_float(
169 opus_encoder_, buffer_.get(), samples_per_10ms_,
170 reinterpret_cast<uint8*>(&out->at(0)), kOpusMaxPayloadSize);
171 if (result > 1) {
172 out->resize(result);
173 return true;
174 } else if (result < 0) {
175 LOG(ERROR) << "Error code from opus_encode_float(): " << result;
176 return false;
177 } else {
178 // Do nothing: The documentation says that a return value of zero or
179 // one byte means the packet does not need to be transmitted.
180 return false;
181 }
182 }
183
184 const scoped_ptr<uint8[]> encoder_memory_;
185 OpusEncoder* const opus_encoder_;
186 const scoped_ptr<float[]> buffer_;
187
188 // This is the recommended value, according to documentation in
189 // third_party/opus/src/include/opus.h, so that the Opus encoder does not
190 // degrade the audio due to memory constraints.
191 //
192 // Note: Whereas other RTP implementations do not, the cast library is
193 // perfectly capable of transporting larger than MTU-sized audio frames.
194 static const int kOpusMaxPayloadSize = 4000;
195
196 DISALLOW_COPY_AND_ASSIGN(OpusImpl);
197 };
198
199 class AudioEncoder::Pcm16Impl : public AudioEncoder::ImplBase {
200 public:
Pcm16Impl(CastEnvironment * cast_environment,int num_channels,int sampling_rate,const FrameEncodedCallback & callback)201 Pcm16Impl(CastEnvironment* cast_environment,
202 int num_channels, int sampling_rate,
203 const FrameEncodedCallback& callback)
204 : ImplBase(cast_environment, kPcm16, num_channels, sampling_rate,
205 callback),
206 buffer_(new int16[num_channels * samples_per_10ms_]) {}
207
~Pcm16Impl()208 virtual ~Pcm16Impl() {}
209
210 private:
TransferSamplesIntoBuffer(const AudioBus * audio_bus,int source_offset,int buffer_fill_offset,int num_samples)211 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus,
212 int source_offset,
213 int buffer_fill_offset,
214 int num_samples) OVERRIDE {
215 audio_bus->ToInterleavedPartial(
216 source_offset, num_samples, sizeof(int16),
217 buffer_.get() + buffer_fill_offset * num_channels_);
218 }
219
EncodeFromFilledBuffer(std::string * out)220 virtual bool EncodeFromFilledBuffer(std::string* out) OVERRIDE {
221 // Output 16-bit PCM integers in big-endian byte order.
222 out->resize(num_channels_ * samples_per_10ms_ * sizeof(int16));
223 const int16* src = buffer_.get();
224 const int16* const src_end = src + num_channels_ * samples_per_10ms_;
225 uint16* dest = reinterpret_cast<uint16*>(&out->at(0));
226 for (; src < src_end; ++src, ++dest)
227 *dest = base::HostToNet16(*src);
228 return true;
229 }
230
231 private:
232 const scoped_ptr<int16[]> buffer_;
233
234 DISALLOW_COPY_AND_ASSIGN(Pcm16Impl);
235 };
236
AudioEncoder(const scoped_refptr<CastEnvironment> & cast_environment,const AudioSenderConfig & audio_config,const FrameEncodedCallback & frame_encoded_callback)237 AudioEncoder::AudioEncoder(
238 const scoped_refptr<CastEnvironment>& cast_environment,
239 const AudioSenderConfig& audio_config,
240 const FrameEncodedCallback& frame_encoded_callback)
241 : cast_environment_(cast_environment) {
242 // Note: It doesn't matter which thread constructs AudioEncoder, just so long
243 // as all calls to InsertAudio() are by the same thread.
244 insert_thread_checker_.DetachFromThread();
245
246 switch (audio_config.codec) {
247 case kOpus:
248 impl_.reset(new OpusImpl(
249 cast_environment, audio_config.channels, audio_config.frequency,
250 audio_config.bitrate, frame_encoded_callback));
251 break;
252 case kPcm16:
253 impl_.reset(new Pcm16Impl(
254 cast_environment, audio_config.channels, audio_config.frequency,
255 frame_encoded_callback));
256 break;
257 default:
258 NOTREACHED() << "Unsupported or unspecified codec for audio encoder";
259 break;
260 }
261 }
262
~AudioEncoder()263 AudioEncoder::~AudioEncoder() {}
264
InsertAudio(const AudioBus * audio_bus,const base::TimeTicks & recorded_time,const base::Closure & done_callback)265 void AudioEncoder::InsertAudio(
266 const AudioBus* audio_bus,
267 const base::TimeTicks& recorded_time,
268 const base::Closure& done_callback) {
269 DCHECK(insert_thread_checker_.CalledOnValidThread());
270 if (!impl_) {
271 NOTREACHED();
272 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
273 done_callback);
274 return;
275 }
276 cast_environment_->PostTask(CastEnvironment::AUDIO_ENCODER, FROM_HERE,
277 base::Bind(&AudioEncoder::EncodeAudio, this, audio_bus, recorded_time,
278 done_callback));
279 }
280
EncodeAudio(const AudioBus * audio_bus,const base::TimeTicks & recorded_time,const base::Closure & done_callback)281 void AudioEncoder::EncodeAudio(
282 const AudioBus* audio_bus,
283 const base::TimeTicks& recorded_time,
284 const base::Closure& done_callback) {
285 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::AUDIO_ENCODER));
286 impl_->EncodeAudio(audio_bus, recorded_time, done_callback);
287 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
288 base::Bind(LogAudioEncodedEvent, cast_environment_, recorded_time));
289 }
290
291 } // namespace cast
292 } // namespace media
293