Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: media/cast/audio_sender/audio_encoder.cc

Issue 149253008: Cast:Refactoring AudioSender to Clang format (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | media/cast/audio_sender/audio_encoder_unittest.cc » ('j') | media/cast/audio_sender/audio_encoder_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698