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