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 <algorithm> |
| 6 |
5 #include "media/base/audio_block_fifo.h" | 7 #include "media/base/audio_block_fifo.h" |
6 | 8 |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
8 | 10 |
9 namespace media { | 11 namespace media { |
10 | 12 |
11 AudioBlockFifo::AudioBlockFifo(int channels, int frames, int blocks) | 13 AudioBlockFifo::AudioBlockFifo(int channels, int frames, int blocks) |
12 : block_frames_(frames), | 14 : channels_(channels), |
| 15 block_frames_(frames), |
13 write_block_(0), | 16 write_block_(0), |
14 read_block_(0), | 17 read_block_(0), |
15 available_blocks_(0), | 18 available_blocks_(0), |
16 write_pos_(0) { | 19 write_pos_(0) { |
17 // Create |blocks| of audio buses and push them to the containers. | 20 IncreaseCapacity(blocks); |
18 audio_blocks_.reserve(blocks); | |
19 for (int i = 0; i < blocks; ++i) { | |
20 scoped_ptr<AudioBus> audio_bus = AudioBus::Create(channels, frames); | |
21 audio_blocks_.push_back(audio_bus.release()); | |
22 } | |
23 } | 21 } |
24 | 22 |
25 AudioBlockFifo::~AudioBlockFifo() {} | 23 AudioBlockFifo::~AudioBlockFifo() {} |
26 | 24 |
27 void AudioBlockFifo::Push(const void* source, | 25 void AudioBlockFifo::Push(const void* source, |
28 int frames, | 26 int frames, |
29 int bytes_per_sample) { | 27 int bytes_per_sample) { |
30 DCHECK(source); | 28 DCHECK(source); |
31 DCHECK_GT(frames, 0); | 29 DCHECK_GT(frames, 0); |
32 DCHECK_GT(bytes_per_sample, 0); | 30 DCHECK_GT(bytes_per_sample, 0); |
33 DCHECK_LT(available_blocks_, static_cast<int>(audio_blocks_.size())); | 31 DCHECK_LT(available_blocks_, static_cast<int>(audio_blocks_.size())); |
| 32 CHECK_LE(frames, GetUnfilledFrames()); |
34 | 33 |
35 const uint8* source_ptr = static_cast<const uint8*>(source); | 34 const uint8* source_ptr = static_cast<const uint8*>(source); |
36 int frames_to_push = frames; | 35 int frames_to_push = frames; |
37 while (frames_to_push) { | 36 while (frames_to_push) { |
38 // Get the current write block. | 37 // Get the current write block. |
39 AudioBus* current_block = audio_blocks_[write_block_]; | 38 AudioBus* current_block = audio_blocks_[write_block_]; |
40 | 39 |
41 // Figure out what segment sizes we need when adding the new content to | 40 // Figure out what segment sizes we need when adding the new content to |
42 // the FIFO. | 41 // the FIFO. |
43 const int push_frames = | 42 const int push_frames = |
44 std::min(block_frames_ - write_pos_, frames_to_push); | 43 std::min(block_frames_ - write_pos_, frames_to_push); |
45 | 44 |
46 // Deinterleave the content to the FIFO and update the |write_pos_|. | 45 // Deinterleave the content to the FIFO and update the |write_pos_|. |
47 current_block->FromInterleavedPartial( | 46 current_block->FromInterleavedPartial( |
48 source_ptr, write_pos_, push_frames, bytes_per_sample); | 47 source_ptr, write_pos_, push_frames, bytes_per_sample); |
49 write_pos_ = (write_pos_ + push_frames) % block_frames_; | 48 write_pos_ = (write_pos_ + push_frames) % block_frames_; |
50 if (!write_pos_) { | 49 if (!write_pos_) { |
51 // The current block is completely filled, increment |write_block_| and | 50 // The current block is completely filled, increment |write_block_| and |
52 // |available_blocks_|. | 51 // |available_blocks_|. |
53 write_block_ = (write_block_ + 1) % audio_blocks_.size(); | 52 write_block_ = (write_block_ + 1) % audio_blocks_.size(); |
54 ++available_blocks_; | 53 ++available_blocks_; |
55 } | 54 } |
56 | 55 |
57 source_ptr += push_frames * bytes_per_sample * current_block->channels(); | 56 source_ptr += push_frames * bytes_per_sample * channels_; |
58 frames_to_push -= push_frames; | 57 frames_to_push -= push_frames; |
59 DCHECK_GE(frames_to_push, 0); | 58 DCHECK_GE(frames_to_push, 0); |
60 } | 59 } |
61 } | 60 } |
62 | 61 |
63 const AudioBus* AudioBlockFifo::Consume() { | 62 const AudioBus* AudioBlockFifo::Consume() { |
64 DCHECK(available_blocks_); | 63 DCHECK(available_blocks_); |
65 AudioBus* audio_bus = audio_blocks_[read_block_]; | 64 AudioBus* audio_bus = audio_blocks_[read_block_]; |
66 read_block_ = (read_block_ + 1) % audio_blocks_.size(); | 65 read_block_ = (read_block_ + 1) % audio_blocks_.size(); |
67 --available_blocks_; | 66 --available_blocks_; |
(...skipping 11 matching lines...) Expand all Loading... |
79 return available_blocks_ * block_frames_ + write_pos_; | 78 return available_blocks_ * block_frames_ + write_pos_; |
80 } | 79 } |
81 | 80 |
82 int AudioBlockFifo::GetUnfilledFrames() const { | 81 int AudioBlockFifo::GetUnfilledFrames() const { |
83 const int unfilled_frames = | 82 const int unfilled_frames = |
84 (audio_blocks_.size() - available_blocks_) * block_frames_ - write_pos_; | 83 (audio_blocks_.size() - available_blocks_) * block_frames_ - write_pos_; |
85 DCHECK_GE(unfilled_frames, 0); | 84 DCHECK_GE(unfilled_frames, 0); |
86 return unfilled_frames; | 85 return unfilled_frames; |
87 } | 86 } |
88 | 87 |
| 88 void AudioBlockFifo::IncreaseCapacity(int blocks) { |
| 89 DCHECK_GT(blocks, 0); |
| 90 |
| 91 // Create |blocks| of audio buses and insert them to the containers. |
| 92 audio_blocks_.reserve(audio_blocks_.size() + blocks); |
| 93 |
| 94 const int original_size = audio_blocks_.size(); |
| 95 for (int i = 0; i < blocks; ++i) { |
| 96 audio_blocks_.push_back( |
| 97 AudioBus::Create(channels_, block_frames_).release()); |
| 98 } |
| 99 |
| 100 if (!original_size) |
| 101 return; |
| 102 |
| 103 std::rotate(audio_blocks_.begin() + read_block_, |
| 104 audio_blocks_.begin() + original_size, |
| 105 audio_blocks_.end()); |
| 106 |
| 107 // Update the write pointer if it is on top of the new inserted blocks. |
| 108 if (write_block_ >= read_block_) |
| 109 write_block_ += blocks; |
| 110 |
| 111 // Update the read pointers correspondingly. |
| 112 read_block_ += blocks; |
| 113 |
| 114 DCHECK_LT(read_block_, static_cast<int>(audio_blocks_.size())); |
| 115 DCHECK_LT(write_block_, static_cast<int>(audio_blocks_.size())); |
| 116 } |
| 117 |
89 } // namespace media | 118 } // namespace media |
OLD | NEW |