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 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: 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 54 virtual ~ImplBase() {} 55 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: 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 149 virtual ~OpusImpl() {} 150 151 private: 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 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: 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 208 virtual ~Pcm16Impl() {} 209 210 private: 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 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 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 263 AudioEncoder::~AudioEncoder() {} 264 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 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