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
3 // found in the LICENSE file.
7 #include "media/base/audio_block_fifo.h"
9 #include "base/logging.h"
13 AudioBlockFifo::AudioBlockFifo(int channels
, int frames
, int blocks
)
14 : channels_(channels
),
15 block_frames_(frames
),
20 IncreaseCapacity(blocks
);
23 AudioBlockFifo::~AudioBlockFifo() {}
25 void AudioBlockFifo::Push(const void* source
,
27 int bytes_per_sample
) {
30 DCHECK_GT(bytes_per_sample
, 0);
31 DCHECK_LT(available_blocks_
, static_cast<int>(audio_blocks_
.size()));
32 CHECK_LE(frames
, GetUnfilledFrames());
34 const uint8
* source_ptr
= static_cast<const uint8
*>(source
);
35 int frames_to_push
= frames
;
36 while (frames_to_push
) {
37 // Get the current write block.
38 AudioBus
* current_block
= audio_blocks_
[write_block_
];
40 // Figure out what segment sizes we need when adding the new content to
42 const int push_frames
=
43 std::min(block_frames_
- write_pos_
, frames_to_push
);
45 // Deinterleave the content to the FIFO and update the |write_pos_|.
46 current_block
->FromInterleavedPartial(
47 source_ptr
, write_pos_
, push_frames
, bytes_per_sample
);
48 write_pos_
= (write_pos_
+ push_frames
) % block_frames_
;
50 // The current block is completely filled, increment |write_block_| and
51 // |available_blocks_|.
52 write_block_
= (write_block_
+ 1) % audio_blocks_
.size();
56 source_ptr
+= push_frames
* bytes_per_sample
* channels_
;
57 frames_to_push
-= push_frames
;
58 DCHECK_GE(frames_to_push
, 0);
62 const AudioBus
* AudioBlockFifo::Consume() {
63 DCHECK(available_blocks_
);
64 AudioBus
* audio_bus
= audio_blocks_
[read_block_
];
65 read_block_
= (read_block_
+ 1) % audio_blocks_
.size();
70 void AudioBlockFifo::Clear() {
74 available_blocks_
= 0;
77 int AudioBlockFifo::GetAvailableFrames() const {
78 return available_blocks_
* block_frames_
+ write_pos_
;
81 int AudioBlockFifo::GetUnfilledFrames() const {
82 const int unfilled_frames
=
83 (audio_blocks_
.size() - available_blocks_
) * block_frames_
- write_pos_
;
84 DCHECK_GE(unfilled_frames
, 0);
85 return unfilled_frames
;
88 void AudioBlockFifo::IncreaseCapacity(int blocks
) {
91 // Create |blocks| of audio buses and insert them to the containers.
92 audio_blocks_
.reserve(audio_blocks_
.size() + blocks
);
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());
103 std::rotate(audio_blocks_
.begin() + read_block_
,
104 audio_blocks_
.begin() + original_size
,
105 audio_blocks_
.end());
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
;
111 // Update the read pointers correspondingly.
112 read_block_
+= blocks
;
114 DCHECK_LT(read_block_
, static_cast<int>(audio_blocks_
.size()));
115 DCHECK_LT(write_block_
, static_cast<int>(audio_blocks_
.size()));