| 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/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/location.h" | 11 #include "base/location.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.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" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 37 // Base class that handles the common problem of feeding one or more AudioBus' | 37 // Base class that handles the common problem of feeding one or more AudioBus' |
| 38 // data into a buffer and then, once the buffer is full, encoding the signal and | 38 // data into a buffer and then, once the buffer is full, encoding the signal and |
| 39 // emitting an EncodedFrame via the FrameEncodedCallback. | 39 // emitting an EncodedFrame via the FrameEncodedCallback. |
| 40 // | 40 // |
| 41 // Subclasses complete the implementation by handling the actual encoding | 41 // Subclasses complete the implementation by handling the actual encoding |
| 42 // details. | 42 // details. |
| 43 class AudioEncoder::ImplBase | 43 class AudioEncoder::ImplBase |
| 44 : public base::RefCountedThreadSafe<AudioEncoder::ImplBase> { | 44 : public base::RefCountedThreadSafe<AudioEncoder::ImplBase> { |
| 45 public: | 45 public: |
| 46 ImplBase(const scoped_refptr<CastEnvironment>& cast_environment, | 46 ImplBase(const scoped_refptr<CastEnvironment>& cast_environment, |
| 47 transport::Codec codec, | 47 Codec codec, |
| 48 int num_channels, | 48 int num_channels, |
| 49 int sampling_rate, | 49 int sampling_rate, |
| 50 const FrameEncodedCallback& callback) | 50 const FrameEncodedCallback& callback) |
| 51 : cast_environment_(cast_environment), | 51 : cast_environment_(cast_environment), |
| 52 codec_(codec), | 52 codec_(codec), |
| 53 num_channels_(num_channels), | 53 num_channels_(num_channels), |
| 54 samples_per_frame_(sampling_rate / kFramesPerSecond), | 54 samples_per_frame_(sampling_rate / kFramesPerSecond), |
| 55 callback_(callback), | 55 callback_(callback), |
| 56 cast_initialization_status_(STATUS_AUDIO_UNINITIALIZED), | 56 cast_initialization_status_(STATUS_AUDIO_UNINITIALIZED), |
| 57 buffer_fill_end_(0), | 57 buffer_fill_end_(0), |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 samples_per_frame_ - buffer_fill_end_, audio_bus->frames() - src_pos); | 110 samples_per_frame_ - buffer_fill_end_, audio_bus->frames() - src_pos); |
| 111 DCHECK_EQ(audio_bus->channels(), num_channels_); | 111 DCHECK_EQ(audio_bus->channels(), num_channels_); |
| 112 TransferSamplesIntoBuffer( | 112 TransferSamplesIntoBuffer( |
| 113 audio_bus.get(), src_pos, buffer_fill_end_, num_samples_to_xfer); | 113 audio_bus.get(), src_pos, buffer_fill_end_, num_samples_to_xfer); |
| 114 src_pos += num_samples_to_xfer; | 114 src_pos += num_samples_to_xfer; |
| 115 buffer_fill_end_ += num_samples_to_xfer; | 115 buffer_fill_end_ += num_samples_to_xfer; |
| 116 | 116 |
| 117 if (buffer_fill_end_ < samples_per_frame_) | 117 if (buffer_fill_end_ < samples_per_frame_) |
| 118 break; | 118 break; |
| 119 | 119 |
| 120 scoped_ptr<transport::EncodedFrame> audio_frame( | 120 scoped_ptr<EncodedFrame> audio_frame( |
| 121 new transport::EncodedFrame()); | 121 new EncodedFrame()); |
| 122 audio_frame->dependency = transport::EncodedFrame::KEY; | 122 audio_frame->dependency = EncodedFrame::KEY; |
| 123 audio_frame->frame_id = frame_id_; | 123 audio_frame->frame_id = frame_id_; |
| 124 audio_frame->referenced_frame_id = frame_id_; | 124 audio_frame->referenced_frame_id = frame_id_; |
| 125 audio_frame->rtp_timestamp = frame_rtp_timestamp_; | 125 audio_frame->rtp_timestamp = frame_rtp_timestamp_; |
| 126 audio_frame->reference_time = frame_capture_time_; | 126 audio_frame->reference_time = frame_capture_time_; |
| 127 | 127 |
| 128 if (EncodeFromFilledBuffer(&audio_frame->data)) { | 128 if (EncodeFromFilledBuffer(&audio_frame->data)) { |
| 129 cast_environment_->PostTask( | 129 cast_environment_->PostTask( |
| 130 CastEnvironment::MAIN, | 130 CastEnvironment::MAIN, |
| 131 FROM_HERE, | 131 FROM_HERE, |
| 132 base::Bind(callback_, base::Passed(&audio_frame))); | 132 base::Bind(callback_, base::Passed(&audio_frame))); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 144 friend class base::RefCountedThreadSafe<ImplBase>; | 144 friend class base::RefCountedThreadSafe<ImplBase>; |
| 145 virtual ~ImplBase() {} | 145 virtual ~ImplBase() {} |
| 146 | 146 |
| 147 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus, | 147 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus, |
| 148 int source_offset, | 148 int source_offset, |
| 149 int buffer_fill_offset, | 149 int buffer_fill_offset, |
| 150 int num_samples) = 0; | 150 int num_samples) = 0; |
| 151 virtual bool EncodeFromFilledBuffer(std::string* out) = 0; | 151 virtual bool EncodeFromFilledBuffer(std::string* out) = 0; |
| 152 | 152 |
| 153 const scoped_refptr<CastEnvironment> cast_environment_; | 153 const scoped_refptr<CastEnvironment> cast_environment_; |
| 154 const transport::Codec codec_; | 154 const Codec codec_; |
| 155 const int num_channels_; | 155 const int num_channels_; |
| 156 const int samples_per_frame_; | 156 const int samples_per_frame_; |
| 157 const FrameEncodedCallback callback_; | 157 const FrameEncodedCallback callback_; |
| 158 | 158 |
| 159 // Subclass' ctor is expected to set this to STATUS_AUDIO_INITIALIZED. | 159 // Subclass' ctor is expected to set this to STATUS_AUDIO_INITIALIZED. |
| 160 CastInitializationStatus cast_initialization_status_; | 160 CastInitializationStatus cast_initialization_status_; |
| 161 | 161 |
| 162 private: | 162 private: |
| 163 // In the case where a call to EncodeAudio() cannot completely fill the | 163 // In the case where a call to EncodeAudio() cannot completely fill the |
| 164 // buffer, this points to the position at which to populate data in a later | 164 // buffer, this points to the position at which to populate data in a later |
| (...skipping 21 matching lines...) Expand all Loading... |
| 186 }; | 186 }; |
| 187 | 187 |
| 188 class AudioEncoder::OpusImpl : public AudioEncoder::ImplBase { | 188 class AudioEncoder::OpusImpl : public AudioEncoder::ImplBase { |
| 189 public: | 189 public: |
| 190 OpusImpl(const scoped_refptr<CastEnvironment>& cast_environment, | 190 OpusImpl(const scoped_refptr<CastEnvironment>& cast_environment, |
| 191 int num_channels, | 191 int num_channels, |
| 192 int sampling_rate, | 192 int sampling_rate, |
| 193 int bitrate, | 193 int bitrate, |
| 194 const FrameEncodedCallback& callback) | 194 const FrameEncodedCallback& callback) |
| 195 : ImplBase(cast_environment, | 195 : ImplBase(cast_environment, |
| 196 transport::CODEC_AUDIO_OPUS, | 196 CODEC_AUDIO_OPUS, |
| 197 num_channels, | 197 num_channels, |
| 198 sampling_rate, | 198 sampling_rate, |
| 199 callback), | 199 callback), |
| 200 encoder_memory_(new uint8[opus_encoder_get_size(num_channels)]), | 200 encoder_memory_(new uint8[opus_encoder_get_size(num_channels)]), |
| 201 opus_encoder_(reinterpret_cast<OpusEncoder*>(encoder_memory_.get())), | 201 opus_encoder_(reinterpret_cast<OpusEncoder*>(encoder_memory_.get())), |
| 202 buffer_(new float[num_channels * samples_per_frame_]) { | 202 buffer_(new float[num_channels * samples_per_frame_]) { |
| 203 if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED) | 203 if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED) |
| 204 return; | 204 return; |
| 205 if (opus_encoder_init(opus_encoder_, | 205 if (opus_encoder_init(opus_encoder_, |
| 206 sampling_rate, | 206 sampling_rate, |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 DISALLOW_COPY_AND_ASSIGN(OpusImpl); | 276 DISALLOW_COPY_AND_ASSIGN(OpusImpl); |
| 277 }; | 277 }; |
| 278 | 278 |
| 279 class AudioEncoder::Pcm16Impl : public AudioEncoder::ImplBase { | 279 class AudioEncoder::Pcm16Impl : public AudioEncoder::ImplBase { |
| 280 public: | 280 public: |
| 281 Pcm16Impl(const scoped_refptr<CastEnvironment>& cast_environment, | 281 Pcm16Impl(const scoped_refptr<CastEnvironment>& cast_environment, |
| 282 int num_channels, | 282 int num_channels, |
| 283 int sampling_rate, | 283 int sampling_rate, |
| 284 const FrameEncodedCallback& callback) | 284 const FrameEncodedCallback& callback) |
| 285 : ImplBase(cast_environment, | 285 : ImplBase(cast_environment, |
| 286 transport::CODEC_AUDIO_PCM16, | 286 CODEC_AUDIO_PCM16, |
| 287 num_channels, | 287 num_channels, |
| 288 sampling_rate, | 288 sampling_rate, |
| 289 callback), | 289 callback), |
| 290 buffer_(new int16[num_channels * samples_per_frame_]) { | 290 buffer_(new int16[num_channels * samples_per_frame_]) { |
| 291 if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED) | 291 if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED) |
| 292 return; | 292 return; |
| 293 cast_initialization_status_ = STATUS_AUDIO_INITIALIZED; | 293 cast_initialization_status_ = STATUS_AUDIO_INITIALIZED; |
| 294 } | 294 } |
| 295 | 295 |
| 296 private: | 296 private: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 322 const scoped_ptr<int16[]> buffer_; | 322 const scoped_ptr<int16[]> buffer_; |
| 323 | 323 |
| 324 DISALLOW_COPY_AND_ASSIGN(Pcm16Impl); | 324 DISALLOW_COPY_AND_ASSIGN(Pcm16Impl); |
| 325 }; | 325 }; |
| 326 | 326 |
| 327 AudioEncoder::AudioEncoder( | 327 AudioEncoder::AudioEncoder( |
| 328 const scoped_refptr<CastEnvironment>& cast_environment, | 328 const scoped_refptr<CastEnvironment>& cast_environment, |
| 329 int num_channels, | 329 int num_channels, |
| 330 int sampling_rate, | 330 int sampling_rate, |
| 331 int bitrate, | 331 int bitrate, |
| 332 transport::Codec codec, | 332 Codec codec, |
| 333 const FrameEncodedCallback& frame_encoded_callback) | 333 const FrameEncodedCallback& frame_encoded_callback) |
| 334 : cast_environment_(cast_environment) { | 334 : cast_environment_(cast_environment) { |
| 335 // Note: It doesn't matter which thread constructs AudioEncoder, just so long | 335 // Note: It doesn't matter which thread constructs AudioEncoder, just so long |
| 336 // as all calls to InsertAudio() are by the same thread. | 336 // as all calls to InsertAudio() are by the same thread. |
| 337 insert_thread_checker_.DetachFromThread(); | 337 insert_thread_checker_.DetachFromThread(); |
| 338 switch (codec) { | 338 switch (codec) { |
| 339 case transport::CODEC_AUDIO_OPUS: | 339 case CODEC_AUDIO_OPUS: |
| 340 impl_ = new OpusImpl(cast_environment, | 340 impl_ = new OpusImpl(cast_environment, |
| 341 num_channels, | 341 num_channels, |
| 342 sampling_rate, | 342 sampling_rate, |
| 343 bitrate, | 343 bitrate, |
| 344 frame_encoded_callback); | 344 frame_encoded_callback); |
| 345 break; | 345 break; |
| 346 case transport::CODEC_AUDIO_PCM16: | 346 case CODEC_AUDIO_PCM16: |
| 347 impl_ = new Pcm16Impl(cast_environment, | 347 impl_ = new Pcm16Impl(cast_environment, |
| 348 num_channels, | 348 num_channels, |
| 349 sampling_rate, | 349 sampling_rate, |
| 350 frame_encoded_callback); | 350 frame_encoded_callback); |
| 351 break; | 351 break; |
| 352 default: | 352 default: |
| 353 NOTREACHED() << "Unsupported or unspecified codec for audio encoder"; | 353 NOTREACHED() << "Unsupported or unspecified codec for audio encoder"; |
| 354 break; | 354 break; |
| 355 } | 355 } |
| 356 } | 356 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 376 cast_environment_->PostTask(CastEnvironment::AUDIO, | 376 cast_environment_->PostTask(CastEnvironment::AUDIO, |
| 377 FROM_HERE, | 377 FROM_HERE, |
| 378 base::Bind(&AudioEncoder::ImplBase::EncodeAudio, | 378 base::Bind(&AudioEncoder::ImplBase::EncodeAudio, |
| 379 impl_, | 379 impl_, |
| 380 base::Passed(&audio_bus), | 380 base::Passed(&audio_bus), |
| 381 recorded_time)); | 381 recorded_time)); |
| 382 } | 382 } |
| 383 | 383 |
| 384 } // namespace cast | 384 } // namespace cast |
| 385 } // namespace media | 385 } // namespace media |
| OLD | NEW |