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" |
(...skipping 20 matching lines...) Expand all Loading... |
31 | 31 |
32 // Base class that handles the common problem of feeding one or more AudioBus' | 32 // 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 | 33 // data into a 10 ms buffer and then, once the buffer is full, encoding the |
34 // signal and emitting an EncodedAudioFrame via the FrameEncodedCallback. | 34 // signal and emitting an EncodedAudioFrame via the FrameEncodedCallback. |
35 // | 35 // |
36 // Subclasses complete the implementation by handling the actual encoding | 36 // Subclasses complete the implementation by handling the actual encoding |
37 // details. | 37 // details. |
38 class AudioEncoder::ImplBase { | 38 class AudioEncoder::ImplBase { |
39 public: | 39 public: |
40 ImplBase(CastEnvironment* cast_environment, | 40 ImplBase(CastEnvironment* cast_environment, |
41 AudioCodec codec, int num_channels, int sampling_rate, | 41 transport::AudioCodec codec, int num_channels, int sampling_rate, |
42 const FrameEncodedCallback& callback) | 42 const FrameEncodedCallback& callback) |
43 : cast_environment_(cast_environment), | 43 : cast_environment_(cast_environment), |
44 codec_(codec), num_channels_(num_channels), | 44 codec_(codec), num_channels_(num_channels), |
45 samples_per_10ms_(sampling_rate / 100), | 45 samples_per_10ms_(sampling_rate / 100), |
46 callback_(callback), | 46 callback_(callback), |
47 buffer_fill_end_(0), | 47 buffer_fill_end_(0), |
48 frame_id_(0) { | 48 frame_id_(0) { |
49 CHECK_GT(num_channels_, 0); | 49 CHECK_GT(num_channels_, 0); |
50 CHECK_GT(samples_per_10ms_, 0); | 50 CHECK_GT(samples_per_10ms_, 0); |
51 CHECK_EQ(sampling_rate % 100, 0); | 51 CHECK_EQ(sampling_rate % 100, 0); |
52 CHECK_LE(samples_per_10ms_ * num_channels_, | 52 CHECK_LE(samples_per_10ms_ * num_channels_, |
53 EncodedAudioFrame::kMaxNumberOfSamples); | 53 transport::EncodedAudioFrame::kMaxNumberOfSamples); |
54 } | 54 } |
55 | 55 |
56 virtual ~ImplBase() {} | 56 virtual ~ImplBase() {} |
57 | 57 |
58 void EncodeAudio(const AudioBus* audio_bus, | 58 void EncodeAudio(const AudioBus* audio_bus, |
59 const base::TimeTicks& recorded_time, | 59 const base::TimeTicks& recorded_time, |
60 const base::Closure& done_callback) { | 60 const base::Closure& done_callback) { |
61 int src_pos = 0; | 61 int src_pos = 0; |
62 while (src_pos < audio_bus->frames()) { | 62 while (src_pos < audio_bus->frames()) { |
63 const int num_samples_to_xfer = | 63 const int num_samples_to_xfer = |
64 std::min(samples_per_10ms_ - buffer_fill_end_, | 64 std::min(samples_per_10ms_ - buffer_fill_end_, |
65 audio_bus->frames() - src_pos); | 65 audio_bus->frames() - src_pos); |
66 DCHECK_EQ(audio_bus->channels(), num_channels_); | 66 DCHECK_EQ(audio_bus->channels(), num_channels_); |
67 TransferSamplesIntoBuffer( | 67 TransferSamplesIntoBuffer( |
68 audio_bus, src_pos, buffer_fill_end_, num_samples_to_xfer); | 68 audio_bus, src_pos, buffer_fill_end_, num_samples_to_xfer); |
69 src_pos += num_samples_to_xfer; | 69 src_pos += num_samples_to_xfer; |
70 buffer_fill_end_ += num_samples_to_xfer; | 70 buffer_fill_end_ += num_samples_to_xfer; |
71 | 71 |
72 if (src_pos == audio_bus->frames()) { | 72 if (src_pos == audio_bus->frames()) { |
73 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 73 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
74 done_callback); | 74 done_callback); |
75 // Note: |audio_bus| is now invalid.. | 75 // Note: |audio_bus| is now invalid.. |
76 } | 76 } |
77 | 77 |
78 if (buffer_fill_end_ == samples_per_10ms_) { | 78 if (buffer_fill_end_ == samples_per_10ms_) { |
79 scoped_ptr<EncodedAudioFrame> audio_frame(new EncodedAudioFrame()); | 79 scoped_ptr<transport::EncodedAudioFrame> audio_frame( |
| 80 new transport::EncodedAudioFrame()); |
80 audio_frame->codec = codec_; | 81 audio_frame->codec = codec_; |
81 audio_frame->frame_id = frame_id_++; | 82 audio_frame->frame_id = frame_id_++; |
82 audio_frame->samples = samples_per_10ms_; | 83 audio_frame->samples = samples_per_10ms_; |
83 if (EncodeFromFilledBuffer(&audio_frame->data)) { | 84 if (EncodeFromFilledBuffer(&audio_frame->data)) { |
84 // Compute an offset to determine the recorded time for the first | 85 // Compute an offset to determine the recorded time for the first |
85 // audio sample in the buffer. | 86 // audio sample in the buffer. |
86 const base::TimeDelta buffer_time_offset = | 87 const base::TimeDelta buffer_time_offset = |
87 (buffer_fill_end_ - src_pos) * | 88 (buffer_fill_end_ - src_pos) * |
88 base::TimeDelta::FromMilliseconds(10) / samples_per_10ms_; | 89 base::TimeDelta::FromMilliseconds(10) / samples_per_10ms_; |
89 // TODO(miu): Consider batching EncodedAudioFrames so we only post a | 90 // TODO(miu): Consider batching EncodedAudioFrames so we only post a |
90 // at most one task for each call to this method. | 91 // at most one task for each call to this method. |
91 cast_environment_->PostTask( | 92 cast_environment_->PostTask( |
92 CastEnvironment::MAIN, FROM_HERE, | 93 CastEnvironment::MAIN, FROM_HERE, |
93 base::Bind(callback_, base::Passed(&audio_frame), | 94 base::Bind(callback_, base::Passed(&audio_frame), |
94 recorded_time - buffer_time_offset)); | 95 recorded_time - buffer_time_offset)); |
95 } | 96 } |
96 buffer_fill_end_ = 0; | 97 buffer_fill_end_ = 0; |
97 } | 98 } |
98 } | 99 } |
99 } | 100 } |
100 | 101 |
101 protected: | 102 protected: |
102 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus, | 103 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus, |
103 int source_offset, | 104 int source_offset, |
104 int buffer_fill_offset, | 105 int buffer_fill_offset, |
105 int num_samples) = 0; | 106 int num_samples) = 0; |
106 virtual bool EncodeFromFilledBuffer(std::string* out) = 0; | 107 virtual bool EncodeFromFilledBuffer(std::string* out) = 0; |
107 | 108 |
108 CastEnvironment* const cast_environment_; | 109 CastEnvironment* const cast_environment_; |
109 const AudioCodec codec_; | 110 const transport::AudioCodec codec_; |
110 const int num_channels_; | 111 const int num_channels_; |
111 const int samples_per_10ms_; | 112 const int samples_per_10ms_; |
112 const FrameEncodedCallback callback_; | 113 const FrameEncodedCallback callback_; |
113 | 114 |
114 private: | 115 private: |
115 // In the case where a call to EncodeAudio() cannot completely fill the | 116 // In the case where a call to EncodeAudio() cannot completely fill the |
116 // buffer, this points to the position at which to populate data in a later | 117 // buffer, this points to the position at which to populate data in a later |
117 // call. | 118 // call. |
118 int buffer_fill_end_; | 119 int buffer_fill_end_; |
119 | 120 |
120 // A counter used to label EncodedAudioFrames. | 121 // A counter used to label EncodedAudioFrames. |
121 uint32 frame_id_; | 122 uint32 frame_id_; |
122 | 123 |
123 private: | 124 private: |
124 DISALLOW_COPY_AND_ASSIGN(ImplBase); | 125 DISALLOW_COPY_AND_ASSIGN(ImplBase); |
125 }; | 126 }; |
126 | 127 |
127 class AudioEncoder::OpusImpl : public AudioEncoder::ImplBase { | 128 class AudioEncoder::OpusImpl : public AudioEncoder::ImplBase { |
128 public: | 129 public: |
129 OpusImpl(CastEnvironment* cast_environment, | 130 OpusImpl(CastEnvironment* cast_environment, |
130 int num_channels, int sampling_rate, int bitrate, | 131 int num_channels, int sampling_rate, int bitrate, |
131 const FrameEncodedCallback& callback) | 132 const FrameEncodedCallback& callback) |
132 : ImplBase(cast_environment, kOpus, num_channels, sampling_rate, | 133 : ImplBase(cast_environment, transport::kOpus, num_channels, |
133 callback), | 134 sampling_rate, callback), |
134 encoder_memory_(new uint8[opus_encoder_get_size(num_channels)]), | 135 encoder_memory_(new uint8[opus_encoder_get_size(num_channels)]), |
135 opus_encoder_(reinterpret_cast<OpusEncoder*>(encoder_memory_.get())), | 136 opus_encoder_(reinterpret_cast<OpusEncoder*>(encoder_memory_.get())), |
136 buffer_(new float[num_channels * samples_per_10ms_]) { | 137 buffer_(new float[num_channels * samples_per_10ms_]) { |
137 CHECK_EQ(opus_encoder_init(opus_encoder_, sampling_rate, num_channels, | 138 CHECK_EQ(opus_encoder_init(opus_encoder_, sampling_rate, num_channels, |
138 OPUS_APPLICATION_AUDIO), | 139 OPUS_APPLICATION_AUDIO), |
139 OPUS_OK); | 140 OPUS_OK); |
140 if (bitrate <= 0) { | 141 if (bitrate <= 0) { |
141 // Note: As of 2013-10-31, the encoder in "auto bitrate" mode would use a | 142 // Note: As of 2013-10-31, the encoder in "auto bitrate" mode would use a |
142 // variable bitrate up to 102kbps for 2-channel, 48 kHz audio and a 10 ms | 143 // variable bitrate up to 102kbps for 2-channel, 48 kHz audio and a 10 ms |
143 // frame size. The opus library authors may, of course, adjust this in | 144 // frame size. The opus library authors may, of course, adjust this in |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 static const int kOpusMaxPayloadSize = 4000; | 197 static const int kOpusMaxPayloadSize = 4000; |
197 | 198 |
198 DISALLOW_COPY_AND_ASSIGN(OpusImpl); | 199 DISALLOW_COPY_AND_ASSIGN(OpusImpl); |
199 }; | 200 }; |
200 | 201 |
201 class AudioEncoder::Pcm16Impl : public AudioEncoder::ImplBase { | 202 class AudioEncoder::Pcm16Impl : public AudioEncoder::ImplBase { |
202 public: | 203 public: |
203 Pcm16Impl(CastEnvironment* cast_environment, | 204 Pcm16Impl(CastEnvironment* cast_environment, |
204 int num_channels, int sampling_rate, | 205 int num_channels, int sampling_rate, |
205 const FrameEncodedCallback& callback) | 206 const FrameEncodedCallback& callback) |
206 : ImplBase(cast_environment, kPcm16, num_channels, sampling_rate, | 207 : ImplBase(cast_environment, transport::kPcm16, num_channels, |
207 callback), | 208 sampling_rate, callback), |
208 buffer_(new int16[num_channels * samples_per_10ms_]) {} | 209 buffer_(new int16[num_channels * samples_per_10ms_]) {} |
209 | 210 |
210 virtual ~Pcm16Impl() {} | 211 virtual ~Pcm16Impl() {} |
211 | 212 |
212 private: | 213 private: |
213 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus, | 214 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus, |
214 int source_offset, | 215 int source_offset, |
215 int buffer_fill_offset, | 216 int buffer_fill_offset, |
216 int num_samples) OVERRIDE { | 217 int num_samples) OVERRIDE { |
217 audio_bus->ToInterleavedPartial( | 218 audio_bus->ToInterleavedPartial( |
(...skipping 21 matching lines...) Expand all Loading... |
239 AudioEncoder::AudioEncoder( | 240 AudioEncoder::AudioEncoder( |
240 const scoped_refptr<CastEnvironment>& cast_environment, | 241 const scoped_refptr<CastEnvironment>& cast_environment, |
241 const AudioSenderConfig& audio_config, | 242 const AudioSenderConfig& audio_config, |
242 const FrameEncodedCallback& frame_encoded_callback) | 243 const FrameEncodedCallback& frame_encoded_callback) |
243 : cast_environment_(cast_environment) { | 244 : cast_environment_(cast_environment) { |
244 // Note: It doesn't matter which thread constructs AudioEncoder, just so long | 245 // Note: It doesn't matter which thread constructs AudioEncoder, just so long |
245 // as all calls to InsertAudio() are by the same thread. | 246 // as all calls to InsertAudio() are by the same thread. |
246 insert_thread_checker_.DetachFromThread(); | 247 insert_thread_checker_.DetachFromThread(); |
247 | 248 |
248 switch (audio_config.codec) { | 249 switch (audio_config.codec) { |
249 case kOpus: | 250 case transport::kOpus: |
250 impl_.reset(new OpusImpl( | 251 impl_.reset(new OpusImpl( |
251 cast_environment, audio_config.channels, audio_config.frequency, | 252 cast_environment, audio_config.channels, audio_config.frequency, |
252 audio_config.bitrate, frame_encoded_callback)); | 253 audio_config.bitrate, frame_encoded_callback)); |
253 break; | 254 break; |
254 case kPcm16: | 255 case transport::kPcm16: |
255 impl_.reset(new Pcm16Impl( | 256 impl_.reset(new Pcm16Impl( |
256 cast_environment, audio_config.channels, audio_config.frequency, | 257 cast_environment, audio_config.channels, audio_config.frequency, |
257 frame_encoded_callback)); | 258 frame_encoded_callback)); |
258 break; | 259 break; |
259 default: | 260 default: |
260 NOTREACHED() << "Unsupported or unspecified codec for audio encoder"; | 261 NOTREACHED() << "Unsupported or unspecified codec for audio encoder"; |
261 break; | 262 break; |
262 } | 263 } |
263 } | 264 } |
264 | 265 |
(...skipping 20 matching lines...) Expand all Loading... |
285 const base::TimeTicks& recorded_time, | 286 const base::TimeTicks& recorded_time, |
286 const base::Closure& done_callback) { | 287 const base::Closure& done_callback) { |
287 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::AUDIO_ENCODER)); | 288 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::AUDIO_ENCODER)); |
288 impl_->EncodeAudio(audio_bus, recorded_time, done_callback); | 289 impl_->EncodeAudio(audio_bus, recorded_time, done_callback); |
289 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, | 290 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
290 base::Bind(LogAudioEncodedEvent, cast_environment_, recorded_time)); | 291 base::Bind(LogAudioEncodedEvent, cast_environment_, recorded_time)); |
291 } | 292 } |
292 | 293 |
293 } // namespace cast | 294 } // namespace cast |
294 } // namespace media | 295 } // namespace media |
OLD | NEW |