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 |