| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/sender/audio_encoder.h" | 5 #include "media/cast/sender/audio_encoder.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 Codec codec, | 49 Codec codec, |
| 50 int num_channels, | 50 int num_channels, |
| 51 int sampling_rate, | 51 int sampling_rate, |
| 52 int samples_per_frame, | 52 int samples_per_frame, |
| 53 const FrameEncodedCallback& callback) | 53 const FrameEncodedCallback& callback) |
| 54 : cast_environment_(cast_environment), | 54 : cast_environment_(cast_environment), |
| 55 codec_(codec), | 55 codec_(codec), |
| 56 num_channels_(num_channels), | 56 num_channels_(num_channels), |
| 57 samples_per_frame_(samples_per_frame), | 57 samples_per_frame_(samples_per_frame), |
| 58 callback_(callback), | 58 callback_(callback), |
| 59 cast_initialization_status_(STATUS_AUDIO_UNINITIALIZED), | 59 operational_status_(STATUS_UNINITIALIZED), |
| 60 frame_duration_(base::TimeDelta::FromMicroseconds( | 60 frame_duration_(base::TimeDelta::FromMicroseconds( |
| 61 base::Time::kMicrosecondsPerSecond * samples_per_frame_ / | 61 base::Time::kMicrosecondsPerSecond * samples_per_frame_ / |
| 62 sampling_rate)), | 62 sampling_rate)), |
| 63 buffer_fill_end_(0), | 63 buffer_fill_end_(0), |
| 64 frame_id_(0), | 64 frame_id_(0), |
| 65 frame_rtp_timestamp_(0), | 65 frame_rtp_timestamp_(0), |
| 66 samples_dropped_from_buffer_(0) { | 66 samples_dropped_from_buffer_(0) { |
| 67 // Support for max sampling rate of 48KHz, 2 channels, 100 ms duration. | 67 // Support for max sampling rate of 48KHz, 2 channels, 100 ms duration. |
| 68 const int kMaxSamplesTimesChannelsPerFrame = 48 * 2 * 100; | 68 const int kMaxSamplesTimesChannelsPerFrame = 48 * 2 * 100; |
| 69 if (num_channels_ <= 0 || samples_per_frame_ <= 0 || | 69 if (num_channels_ <= 0 || samples_per_frame_ <= 0 || |
| 70 frame_duration_ == base::TimeDelta() || | 70 frame_duration_ == base::TimeDelta() || |
| 71 samples_per_frame_ * num_channels_ > kMaxSamplesTimesChannelsPerFrame) { | 71 samples_per_frame_ * num_channels_ > kMaxSamplesTimesChannelsPerFrame) { |
| 72 cast_initialization_status_ = STATUS_INVALID_AUDIO_CONFIGURATION; | 72 operational_status_ = STATUS_INVALID_CONFIGURATION; |
| 73 } | 73 } |
| 74 } | 74 } |
| 75 | 75 |
| 76 CastInitializationStatus InitializationResult() const { | 76 OperationalStatus InitializationResult() const { |
| 77 return cast_initialization_status_; | 77 return operational_status_; |
| 78 } | 78 } |
| 79 | 79 |
| 80 int samples_per_frame() const { | 80 int samples_per_frame() const { |
| 81 return samples_per_frame_; | 81 return samples_per_frame_; |
| 82 } | 82 } |
| 83 | 83 |
| 84 base::TimeDelta frame_duration() const { return frame_duration_; } | 84 base::TimeDelta frame_duration() const { return frame_duration_; } |
| 85 | 85 |
| 86 void EncodeAudio(scoped_ptr<AudioBus> audio_bus, | 86 void EncodeAudio(scoped_ptr<AudioBus> audio_bus, |
| 87 const base::TimeTicks& recorded_time) { | 87 const base::TimeTicks& recorded_time) { |
| 88 DCHECK_EQ(cast_initialization_status_, STATUS_AUDIO_INITIALIZED); | 88 DCHECK_EQ(operational_status_, STATUS_INITIALIZED); |
| 89 DCHECK(!recorded_time.is_null()); | 89 DCHECK(!recorded_time.is_null()); |
| 90 | 90 |
| 91 // Determine whether |recorded_time| is consistent with the amount of audio | 91 // Determine whether |recorded_time| is consistent with the amount of audio |
| 92 // data having been processed in the past. Resolve the underrun problem by | 92 // data having been processed in the past. Resolve the underrun problem by |
| 93 // dropping data from the internal buffer and skipping ahead the next | 93 // dropping data from the internal buffer and skipping ahead the next |
| 94 // frame's RTP timestamp by the estimated number of frames missed. On the | 94 // frame's RTP timestamp by the estimated number of frames missed. On the |
| 95 // other hand, don't attempt to resolve overruns: A receiver should | 95 // other hand, don't attempt to resolve overruns: A receiver should |
| 96 // gracefully deal with an excess of audio data. | 96 // gracefully deal with an excess of audio data. |
| 97 base::TimeDelta buffer_fill_duration = | 97 base::TimeDelta buffer_fill_duration = |
| 98 buffer_fill_end_ * frame_duration_ / samples_per_frame_; | 98 buffer_fill_end_ * frame_duration_ / samples_per_frame_; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 int buffer_fill_offset, | 162 int buffer_fill_offset, |
| 163 int num_samples) = 0; | 163 int num_samples) = 0; |
| 164 virtual bool EncodeFromFilledBuffer(std::string* out) = 0; | 164 virtual bool EncodeFromFilledBuffer(std::string* out) = 0; |
| 165 | 165 |
| 166 const scoped_refptr<CastEnvironment> cast_environment_; | 166 const scoped_refptr<CastEnvironment> cast_environment_; |
| 167 const Codec codec_; | 167 const Codec codec_; |
| 168 const int num_channels_; | 168 const int num_channels_; |
| 169 const int samples_per_frame_; | 169 const int samples_per_frame_; |
| 170 const FrameEncodedCallback callback_; | 170 const FrameEncodedCallback callback_; |
| 171 | 171 |
| 172 // Subclass' ctor is expected to set this to STATUS_AUDIO_INITIALIZED. | 172 // Subclass' ctor is expected to set this to STATUS_INITIALIZED. |
| 173 CastInitializationStatus cast_initialization_status_; | 173 OperationalStatus operational_status_; |
| 174 | 174 |
| 175 // The duration of one frame of encoded audio samples. Derived from | 175 // The duration of one frame of encoded audio samples. Derived from |
| 176 // |samples_per_frame_| and the sampling rate. | 176 // |samples_per_frame_| and the sampling rate. |
| 177 const base::TimeDelta frame_duration_; | 177 const base::TimeDelta frame_duration_; |
| 178 | 178 |
| 179 private: | 179 private: |
| 180 // In the case where a call to EncodeAudio() cannot completely fill the | 180 // In the case where a call to EncodeAudio() cannot completely fill the |
| 181 // buffer, this points to the position at which to populate data in a later | 181 // buffer, this points to the position at which to populate data in a later |
| 182 // call. | 182 // call. |
| 183 int buffer_fill_end_; | 183 int buffer_fill_end_; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 const FrameEncodedCallback& callback) | 216 const FrameEncodedCallback& callback) |
| 217 : ImplBase(cast_environment, | 217 : ImplBase(cast_environment, |
| 218 CODEC_AUDIO_OPUS, | 218 CODEC_AUDIO_OPUS, |
| 219 num_channels, | 219 num_channels, |
| 220 sampling_rate, | 220 sampling_rate, |
| 221 sampling_rate / kDefaultFramesPerSecond, /* 10 ms frames */ | 221 sampling_rate / kDefaultFramesPerSecond, /* 10 ms frames */ |
| 222 callback), | 222 callback), |
| 223 encoder_memory_(new uint8[opus_encoder_get_size(num_channels)]), | 223 encoder_memory_(new uint8[opus_encoder_get_size(num_channels)]), |
| 224 opus_encoder_(reinterpret_cast<OpusEncoder*>(encoder_memory_.get())), | 224 opus_encoder_(reinterpret_cast<OpusEncoder*>(encoder_memory_.get())), |
| 225 buffer_(new float[num_channels * samples_per_frame_]) { | 225 buffer_(new float[num_channels * samples_per_frame_]) { |
| 226 if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED || | 226 if (ImplBase::operational_status_ != STATUS_UNINITIALIZED || |
| 227 sampling_rate % samples_per_frame_ != 0 || | 227 sampling_rate % samples_per_frame_ != 0 || |
| 228 !IsValidFrameDuration(frame_duration_)) { | 228 !IsValidFrameDuration(frame_duration_)) { |
| 229 return; | 229 return; |
| 230 } | 230 } |
| 231 if (opus_encoder_init(opus_encoder_, | 231 if (opus_encoder_init(opus_encoder_, |
| 232 sampling_rate, | 232 sampling_rate, |
| 233 num_channels, | 233 num_channels, |
| 234 OPUS_APPLICATION_AUDIO) != OPUS_OK) { | 234 OPUS_APPLICATION_AUDIO) != OPUS_OK) { |
| 235 ImplBase::cast_initialization_status_ = | 235 ImplBase::operational_status_ = STATUS_INVALID_CONFIGURATION; |
| 236 STATUS_INVALID_AUDIO_CONFIGURATION; | |
| 237 return; | 236 return; |
| 238 } | 237 } |
| 239 ImplBase::cast_initialization_status_ = STATUS_AUDIO_INITIALIZED; | 238 ImplBase::operational_status_ = STATUS_INITIALIZED; |
| 240 | 239 |
| 241 if (bitrate <= 0) { | 240 if (bitrate <= 0) { |
| 242 // Note: As of 2013-10-31, the encoder in "auto bitrate" mode would use a | 241 // Note: As of 2013-10-31, the encoder in "auto bitrate" mode would use a |
| 243 // variable bitrate up to 102kbps for 2-channel, 48 kHz audio and a 10 ms | 242 // variable bitrate up to 102kbps for 2-channel, 48 kHz audio and a 10 ms |
| 244 // frame size. The opus library authors may, of course, adjust this in | 243 // frame size. The opus library authors may, of course, adjust this in |
| 245 // later versions. | 244 // later versions. |
| 246 bitrate = OPUS_AUTO; | 245 bitrate = OPUS_AUTO; |
| 247 } | 246 } |
| 248 CHECK_EQ(opus_encoder_ctl(opus_encoder_, OPUS_SET_BITRATE(bitrate)), | 247 CHECK_EQ(opus_encoder_ctl(opus_encoder_, OPUS_SET_BITRATE(bitrate)), |
| 249 OPUS_OK); | 248 OPUS_OK); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 kAccessUnitSamples, | 335 kAccessUnitSamples, |
| 337 callback), | 336 callback), |
| 338 input_buffer_(AudioBus::Create(num_channels, kAccessUnitSamples)), | 337 input_buffer_(AudioBus::Create(num_channels, kAccessUnitSamples)), |
| 339 input_bus_(AudioBus::CreateWrapper(num_channels)), | 338 input_bus_(AudioBus::CreateWrapper(num_channels)), |
| 340 max_access_unit_size_(0), | 339 max_access_unit_size_(0), |
| 341 output_buffer_(nullptr), | 340 output_buffer_(nullptr), |
| 342 converter_(nullptr), | 341 converter_(nullptr), |
| 343 file_(nullptr), | 342 file_(nullptr), |
| 344 num_access_units_(0), | 343 num_access_units_(0), |
| 345 can_resume_(true) { | 344 can_resume_(true) { |
| 346 if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED) { | 345 if (ImplBase::operational_status_ != STATUS_UNINITIALIZED) { |
| 347 return; | 346 return; |
| 348 } | 347 } |
| 349 if (!Initialize(sampling_rate, bitrate)) { | 348 if (!Initialize(sampling_rate, bitrate)) { |
| 350 ImplBase::cast_initialization_status_ = | 349 ImplBase::operational_status_ = STATUS_INVALID_CONFIGURATION; |
| 351 STATUS_INVALID_AUDIO_CONFIGURATION; | |
| 352 return; | 350 return; |
| 353 } | 351 } |
| 354 ImplBase::cast_initialization_status_ = STATUS_AUDIO_INITIALIZED; | 352 ImplBase::operational_status_ = STATUS_INITIALIZED; |
| 355 } | 353 } |
| 356 | 354 |
| 357 private: | 355 private: |
| 358 ~AppleAacImpl() override { Teardown(); } | 356 ~AppleAacImpl() override { Teardown(); } |
| 359 | 357 |
| 360 // Destroys the existing audio converter and file, if any. | 358 // Destroys the existing audio converter and file, if any. |
| 361 void Teardown() { | 359 void Teardown() { |
| 362 if (converter_) { | 360 if (converter_) { |
| 363 AudioConverterDispose(converter_); | 361 AudioConverterDispose(converter_); |
| 364 converter_ = nullptr; | 362 converter_ = nullptr; |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 int num_channels, | 698 int num_channels, |
| 701 int sampling_rate, | 699 int sampling_rate, |
| 702 const FrameEncodedCallback& callback) | 700 const FrameEncodedCallback& callback) |
| 703 : ImplBase(cast_environment, | 701 : ImplBase(cast_environment, |
| 704 CODEC_AUDIO_PCM16, | 702 CODEC_AUDIO_PCM16, |
| 705 num_channels, | 703 num_channels, |
| 706 sampling_rate, | 704 sampling_rate, |
| 707 sampling_rate / kDefaultFramesPerSecond, /* 10 ms frames */ | 705 sampling_rate / kDefaultFramesPerSecond, /* 10 ms frames */ |
| 708 callback), | 706 callback), |
| 709 buffer_(new int16[num_channels * samples_per_frame_]) { | 707 buffer_(new int16[num_channels * samples_per_frame_]) { |
| 710 if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED) | 708 if (ImplBase::operational_status_ != STATUS_UNINITIALIZED) |
| 711 return; | 709 return; |
| 712 cast_initialization_status_ = STATUS_AUDIO_INITIALIZED; | 710 operational_status_ = STATUS_INITIALIZED; |
| 713 } | 711 } |
| 714 | 712 |
| 715 private: | 713 private: |
| 716 ~Pcm16Impl() override {} | 714 ~Pcm16Impl() override {} |
| 717 | 715 |
| 718 void TransferSamplesIntoBuffer(const AudioBus* audio_bus, | 716 void TransferSamplesIntoBuffer(const AudioBus* audio_bus, |
| 719 int source_offset, | 717 int source_offset, |
| 720 int buffer_fill_offset, | 718 int buffer_fill_offset, |
| 721 int num_samples) override { | 719 int num_samples) override { |
| 722 audio_bus->ToInterleavedPartial( | 720 audio_bus->ToInterleavedPartial( |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 frame_encoded_callback); | 778 frame_encoded_callback); |
| 781 break; | 779 break; |
| 782 default: | 780 default: |
| 783 NOTREACHED() << "Unsupported or unspecified codec for audio encoder"; | 781 NOTREACHED() << "Unsupported or unspecified codec for audio encoder"; |
| 784 break; | 782 break; |
| 785 } | 783 } |
| 786 } | 784 } |
| 787 | 785 |
| 788 AudioEncoder::~AudioEncoder() {} | 786 AudioEncoder::~AudioEncoder() {} |
| 789 | 787 |
| 790 CastInitializationStatus AudioEncoder::InitializationResult() const { | 788 OperationalStatus AudioEncoder::InitializationResult() const { |
| 791 DCHECK(insert_thread_checker_.CalledOnValidThread()); | 789 DCHECK(insert_thread_checker_.CalledOnValidThread()); |
| 792 if (impl_.get()) { | 790 if (impl_.get()) { |
| 793 return impl_->InitializationResult(); | 791 return impl_->InitializationResult(); |
| 794 } | 792 } |
| 795 return STATUS_UNSUPPORTED_AUDIO_CODEC; | 793 return STATUS_UNSUPPORTED_CODEC; |
| 796 } | 794 } |
| 797 | 795 |
| 798 int AudioEncoder::GetSamplesPerFrame() const { | 796 int AudioEncoder::GetSamplesPerFrame() const { |
| 799 DCHECK(insert_thread_checker_.CalledOnValidThread()); | 797 DCHECK(insert_thread_checker_.CalledOnValidThread()); |
| 800 if (InitializationResult() != STATUS_AUDIO_INITIALIZED) { | 798 if (InitializationResult() != STATUS_INITIALIZED) { |
| 801 NOTREACHED(); | 799 NOTREACHED(); |
| 802 return std::numeric_limits<int>::max(); | 800 return std::numeric_limits<int>::max(); |
| 803 } | 801 } |
| 804 return impl_->samples_per_frame(); | 802 return impl_->samples_per_frame(); |
| 805 } | 803 } |
| 806 | 804 |
| 807 base::TimeDelta AudioEncoder::GetFrameDuration() const { | 805 base::TimeDelta AudioEncoder::GetFrameDuration() const { |
| 808 DCHECK(insert_thread_checker_.CalledOnValidThread()); | 806 DCHECK(insert_thread_checker_.CalledOnValidThread()); |
| 809 if (InitializationResult() != STATUS_AUDIO_INITIALIZED) { | 807 if (InitializationResult() != STATUS_INITIALIZED) { |
| 810 NOTREACHED(); | 808 NOTREACHED(); |
| 811 return base::TimeDelta(); | 809 return base::TimeDelta(); |
| 812 } | 810 } |
| 813 return impl_->frame_duration(); | 811 return impl_->frame_duration(); |
| 814 } | 812 } |
| 815 | 813 |
| 816 void AudioEncoder::InsertAudio(scoped_ptr<AudioBus> audio_bus, | 814 void AudioEncoder::InsertAudio(scoped_ptr<AudioBus> audio_bus, |
| 817 const base::TimeTicks& recorded_time) { | 815 const base::TimeTicks& recorded_time) { |
| 818 DCHECK(insert_thread_checker_.CalledOnValidThread()); | 816 DCHECK(insert_thread_checker_.CalledOnValidThread()); |
| 819 DCHECK(audio_bus.get()); | 817 DCHECK(audio_bus.get()); |
| 820 if (InitializationResult() != STATUS_AUDIO_INITIALIZED) { | 818 if (InitializationResult() != STATUS_INITIALIZED) { |
| 821 NOTREACHED(); | 819 NOTREACHED(); |
| 822 return; | 820 return; |
| 823 } | 821 } |
| 824 cast_environment_->PostTask(CastEnvironment::AUDIO, | 822 cast_environment_->PostTask(CastEnvironment::AUDIO, |
| 825 FROM_HERE, | 823 FROM_HERE, |
| 826 base::Bind(&AudioEncoder::ImplBase::EncodeAudio, | 824 base::Bind(&AudioEncoder::ImplBase::EncodeAudio, |
| 827 impl_, | 825 impl_, |
| 828 base::Passed(&audio_bus), | 826 base::Passed(&audio_bus), |
| 829 recorded_time)); | 827 recorded_time)); |
| 830 } | 828 } |
| 831 | 829 |
| 832 } // namespace cast | 830 } // namespace cast |
| 833 } // namespace media | 831 } // namespace media |
| OLD | NEW |