OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "content/renderer/media/audio_track_recorder.h" | 5 #include "content/renderer/media/audio_track_recorder.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 data_out->resize(result); | 68 data_out->resize(result); |
69 return true; | 69 return true; |
70 } | 70 } |
71 // If |result| in {0,1}, do nothing; the documentation says that a return | 71 // If |result| in {0,1}, do nothing; the documentation says that a return |
72 // value of zero or one means the packet does not need to be transmitted. | 72 // value of zero or one means the packet does not need to be transmitted. |
73 // Otherwise, we have an error. | 73 // Otherwise, we have an error. |
74 DLOG_IF(ERROR, result < 0) << " encode failed: " << opus_strerror(result); | 74 DLOG_IF(ERROR, result < 0) << " encode failed: " << opus_strerror(result); |
75 return false; | 75 return false; |
76 } | 76 } |
77 | 77 |
78 // Interleaves |audio_bus| channels() of floats into a single output linear | |
79 // |buffer|. | |
80 // TODO(mcasas) https://crbug.com/580391 use AudioBus::ToInterleavedFloat(). | |
81 void ToInterleaved(media::AudioBus* audio_bus, float* buffer) { | |
82 for (int ch = 0; ch < audio_bus->channels(); ++ch) { | |
83 const float* src = audio_bus->channel(ch); | |
84 const float* const src_end = src + audio_bus->frames(); | |
85 float* dest = buffer + ch; | |
86 for (; src < src_end; ++src, dest += audio_bus->channels()) | |
87 *dest = *src; | |
88 } | |
89 } | |
90 | |
91 } // anonymous namespace | 78 } // anonymous namespace |
92 | 79 |
93 // Nested class encapsulating opus-related encoding details. It contains an | 80 // Nested class encapsulating opus-related encoding details. It contains an |
94 // AudioConverter to adapt incoming data to the format Opus likes to have. | 81 // AudioConverter to adapt incoming data to the format Opus likes to have. |
95 // AudioEncoder is created and destroyed on ATR's main thread (usually the main | 82 // AudioEncoder is created and destroyed on ATR's main thread (usually the main |
96 // render thread) but otherwise should operate entirely on |encoder_thread_|, | 83 // render thread) but otherwise should operate entirely on |encoder_thread_|, |
97 // which is owned by AudioTrackRecorder. Be sure to delete |encoder_thread_| | 84 // which is owned by AudioTrackRecorder. Be sure to delete |encoder_thread_| |
98 // before deleting the AudioEncoder using it. | 85 // before deleting the AudioEncoder using it. |
99 class AudioTrackRecorder::AudioEncoder | 86 class AudioTrackRecorder::AudioEncoder |
100 : public base::RefCountedThreadSafe<AudioEncoder>, | 87 : public base::RefCountedThreadSafe<AudioEncoder>, |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 // TODO(mcasas): Consider using a std::deque<scoped_ptr<AudioBus>> instead of | 232 // TODO(mcasas): Consider using a std::deque<scoped_ptr<AudioBus>> instead of |
246 // an AudioFifo, to avoid copying data needlessly since we know the sizes of | 233 // an AudioFifo, to avoid copying data needlessly since we know the sizes of |
247 // both input and output and they are multiples. | 234 // both input and output and they are multiples. |
248 fifo_->Push(input_bus.get()); | 235 fifo_->Push(input_bus.get()); |
249 | 236 |
250 // Wait to have enough |input_bus|s to guarantee a satisfactory conversion. | 237 // Wait to have enough |input_bus|s to guarantee a satisfactory conversion. |
251 while (fifo_->frames() >= input_params_.frames_per_buffer()) { | 238 while (fifo_->frames() >= input_params_.frames_per_buffer()) { |
252 scoped_ptr<media::AudioBus> audio_bus = media::AudioBus::Create( | 239 scoped_ptr<media::AudioBus> audio_bus = media::AudioBus::Create( |
253 output_params_.channels(), kOpusPreferredFramesPerBuffer); | 240 output_params_.channels(), kOpusPreferredFramesPerBuffer); |
254 converter_->Convert(audio_bus.get()); | 241 converter_->Convert(audio_bus.get()); |
255 ToInterleaved(audio_bus.get(), buffer_.get()); | 242 audio_bus->ToInterleavedFloat(0, 0, audio_bus->frames(), |
| 243 buffer_.get()); |
256 | 244 |
257 scoped_ptr<std::string> encoded_data(new std::string()); | 245 scoped_ptr<std::string> encoded_data(new std::string()); |
258 if (DoEncode(opus_encoder_, buffer_.get(), kOpusPreferredFramesPerBuffer, | 246 if (DoEncode(opus_encoder_, buffer_.get(), kOpusPreferredFramesPerBuffer, |
259 encoded_data.get())) { | 247 encoded_data.get())) { |
260 const base::TimeTicks capture_time_of_first_sample = | 248 const base::TimeTicks capture_time_of_first_sample = |
261 capture_time - | 249 capture_time - |
262 base::TimeDelta::FromMicroseconds(fifo_->frames() * | 250 base::TimeDelta::FromMicroseconds(fifo_->frames() * |
263 base::Time::kMicrosecondsPerSecond / | 251 base::Time::kMicrosecondsPerSecond / |
264 input_params_.sample_rate()); | 252 input_params_.sample_rate()); |
265 on_encoded_audio_cb_.Run(output_params_, std::move(encoded_data), | 253 on_encoded_audio_cb_.Run(output_params_, std::move(encoded_data), |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 scoped_ptr<media::AudioBus> audio_data = | 317 scoped_ptr<media::AudioBus> audio_data = |
330 media::AudioBus::Create(audio_bus.channels(), audio_bus.frames()); | 318 media::AudioBus::Create(audio_bus.channels(), audio_bus.frames()); |
331 audio_bus.CopyTo(audio_data.get()); | 319 audio_bus.CopyTo(audio_data.get()); |
332 | 320 |
333 encoder_thread_.task_runner()->PostTask( | 321 encoder_thread_.task_runner()->PostTask( |
334 FROM_HERE, base::Bind(&AudioEncoder::EncodeAudio, encoder_, | 322 FROM_HERE, base::Bind(&AudioEncoder::EncodeAudio, encoder_, |
335 base::Passed(&audio_data), capture_time)); | 323 base::Passed(&audio_data), capture_time)); |
336 } | 324 } |
337 | 325 |
338 } // namespace content | 326 } // namespace content |
OLD | NEW |