Index: media/base/audio_rechunker.cc |
diff --git a/media/base/audio_rechunker.cc b/media/base/audio_rechunker.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c898cd249667f0c3b2ca08dacf5a8359035343e9 |
--- /dev/null |
+++ b/media/base/audio_rechunker.cc |
@@ -0,0 +1,84 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "media/base/audio_rechunker.h" |
+ |
+#include <algorithm> |
+ |
+namespace media { |
+ |
+AudioRechunker::AudioRechunker(base::TimeDelta output_duration, |
+ const RechunkedAudioCallback& callback) |
+ : output_duration_(output_duration), |
+ callback_(callback), |
+ sample_rate_(0), |
+ output_frames_(0) { |
+ DCHECK_GT(output_duration_, base::TimeDelta()); |
+ DCHECK(!callback_.is_null()); |
+} |
+ |
+AudioRechunker::~AudioRechunker() {} |
+ |
+bool AudioRechunker::SetSampleRate(int sample_rate) { |
+ DCHECK_GT(sample_rate, 0); |
+ |
+ sample_rate_ = sample_rate; |
+ audio_queue_.reset(); |
xjz
2016/02/20 01:53:04
Same as the other comment, I think here also assum
miu
2016/02/23 04:27:41
That's not the assumption. See my reply to your o
|
+ pending_frames_ = 0; |
+ |
+ const int64_t numerator = sample_rate * output_duration_.InMicroseconds(); |
+ output_frames_ = numerator / base::Time::kMicrosecondsPerSecond; |
+ DCHECK_GT(output_frames_, 0); |
+ return ((numerator % base::Time::kMicrosecondsPerSecond) == 0); |
+} |
+ |
+void AudioRechunker::Push(const AudioBus& input_bus, |
+ base::TimeDelta reference_timestamp) { |
+ DCHECK_GT(output_frames_, 0); |
+ |
+ // Fast path: No buffering required. |
+ if ((pending_frames_ == 0) && (input_bus.frames() == output_frames_)) { |
+ callback_.Run(input_bus, reference_timestamp); |
+ return; |
+ } |
+ |
+ // Lazy-create the |audio_queue_| if needed. |
+ if (!audio_queue_ || audio_queue_->channels() != input_bus.channels()) |
+ audio_queue_ = AudioBus::Create(input_bus.channels(), output_frames_); |
+ |
+ // Adjust |reference_timestamp| to be that of the first sample in |
+ // |audio_queue_| since that will be the first sample delivered via the |
+ // |callback_|. |
+ reference_timestamp -= base::TimeDelta::FromMicroseconds( |
+ pending_frames_ * base::Time::kMicrosecondsPerSecond / sample_rate_); |
+ |
+ // Repeatedly fill up |audio_queue_| with more sample frames from |input_bus| |
o1ka
2016/02/22 13:04:47
I find the part below a bit difficult to read due
miu
2016/02/23 04:27:41
Acknowledged.
|
+ // and deliver batches until all sample frames in |input_bus| have been |
+ // consumed. |
+ int source_pos = 0; |
o1ka
2016/02/22 13:04:47
Can it be named |input_bus_offset| or something li
miu
2016/02/23 04:27:41
Done. Changed to input_offset.
|
+ do { |
+ // Attempt to fill |audio_queue_| completely. |
+ const int frames_to_push = |
o1ka
2016/02/22 13:04:47
|frames_to_queue|? As I see it, frames_to_push are
miu
2016/02/23 04:27:41
Done. Changed to frames_to_enqueue.
|
+ std::min(static_cast<int>(input_bus.frames() - source_pos), |
+ output_frames_ - pending_frames_); |
+ if (frames_to_push > 0) { |
+ DVLOG(2) << "Enqueuing " << frames_to_push << " frames."; |
+ input_bus.CopyPartialFramesTo(source_pos, frames_to_push, pending_frames_, |
+ audio_queue_.get()); |
o1ka
2016/02/22 13:04:47
It would be also nice to somehow associate |pendin
miu
2016/02/23 04:27:41
Done.
|
+ pending_frames_ += frames_to_push; |
+ source_pos += frames_to_push; |
+ } |
+ |
+ // If |audio_queue_| has been filled completely, deliver the re-chunked |
+ // audio to the consumer. |
+ if (pending_frames_ == output_frames_) { |
xjz
2016/02/20 01:53:04
Does here assume that for each Push, the input fra
miu
2016/02/23 04:27:41
No, that's not the assumption at all. The number
|
+ DVLOG(2) << "Delivering another " << pending_frames_ << " frames."; |
+ callback_.Run(*audio_queue_, reference_timestamp); |
+ reference_timestamp += output_duration_; |
+ pending_frames_ = 0; |
+ } |
o1ka
2016/02/22 13:04:47
To improve readability, it would be nice to have a
miu
2016/02/23 04:27:41
Done.
|
+ } while (source_pos < input_bus.frames()); |
+} |
+ |
+} // namespace media |