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
3 // found in the LICENSE file.
5 #include "media/base/audio_buffer_queue.h"
9 #include "base/logging.h"
10 #include "media/base/audio_bus.h"
11 #include "media/base/buffers.h"
15 AudioBufferQueue::AudioBufferQueue() { Clear(); }
16 AudioBufferQueue::~AudioBufferQueue() {}
18 void AudioBufferQueue::Clear() {
20 current_buffer_
= buffers_
.begin();
21 current_buffer_offset_
= 0;
25 void AudioBufferQueue::Append(const scoped_refptr
<AudioBuffer
>& buffer_in
) {
26 // Add the buffer to the queue. Inserting into deque invalidates all
27 // iterators, so point to the first buffer.
28 buffers_
.push_back(buffer_in
);
29 current_buffer_
= buffers_
.begin();
31 // Update the |frames_| counter since we have added frames.
32 frames_
+= buffer_in
->frame_count();
33 CHECK_GT(frames_
, 0); // make sure it doesn't overflow.
36 int AudioBufferQueue::ReadFrames(int frames
,
37 int dest_frame_offset
,
39 DCHECK_GE(dest
->frames(), frames
+ dest_frame_offset
);
40 return InternalRead(frames
, true, 0, dest_frame_offset
, dest
);
43 int AudioBufferQueue::PeekFrames(int frames
,
44 int source_frame_offset
,
45 int dest_frame_offset
,
47 DCHECK_GE(dest
->frames(), frames
);
49 frames
, false, source_frame_offset
, dest_frame_offset
, dest
);
52 void AudioBufferQueue::SeekFrames(int frames
) {
53 // Perform seek only if we have enough bytes in the queue.
54 CHECK_LE(frames
, frames_
);
55 int taken
= InternalRead(frames
, true, 0, 0, NULL
);
56 DCHECK_EQ(taken
, frames
);
59 int AudioBufferQueue::InternalRead(int frames
,
60 bool advance_position
,
61 int source_frame_offset
,
62 int dest_frame_offset
,
64 // Counts how many frames are actually read from the buffer queue.
66 BufferQueue::iterator current_buffer
= current_buffer_
;
67 int current_buffer_offset
= current_buffer_offset_
;
69 int frames_to_skip
= source_frame_offset
;
70 while (taken
< frames
) {
71 // |current_buffer| is valid since the first time this buffer is appended
72 // with data. Make sure there is data to be processed.
73 if (current_buffer
== buffers_
.end())
76 scoped_refptr
<AudioBuffer
> buffer
= *current_buffer
;
78 int remaining_frames_in_buffer
=
79 buffer
->frame_count() - current_buffer_offset
;
81 if (frames_to_skip
> 0) {
82 // If there are frames to skip, do it first. May need to skip into
83 // subsequent buffers.
84 int skipped
= std::min(remaining_frames_in_buffer
, frames_to_skip
);
85 current_buffer_offset
+= skipped
;
86 frames_to_skip
-= skipped
;
88 // Find the right amount to copy from the current buffer. We shall copy no
89 // more than |frames| frames in total and each single step copies no more
90 // than the current buffer size.
91 int copied
= std::min(frames
- taken
, remaining_frames_in_buffer
);
93 // if |dest| is NULL, there's no need to copy.
96 copied
, current_buffer_offset
, dest_frame_offset
+ taken
, dest
);
99 // Increase total number of frames copied, which regulates when to end
103 // We have read |copied| frames from the current buffer. Advance the
105 current_buffer_offset
+= copied
;
108 // Has the buffer has been consumed?
109 if (current_buffer_offset
== buffer
->frame_count()) {
110 // If we are at the last buffer, no more data to be copied, so stop.
111 BufferQueue::iterator next
= current_buffer
+ 1;
112 if (next
== buffers_
.end())
115 // Advances the iterator.
116 current_buffer
= next
;
117 current_buffer_offset
= 0;
121 if (advance_position
) {
122 // Update the appropriate values since |taken| frames have been copied out.
124 DCHECK_GE(frames_
, 0);
125 DCHECK(current_buffer_
!= buffers_
.end() || frames_
== 0);
127 // Remove any buffers before the current buffer as there is no going
129 buffers_
.erase(buffers_
.begin(), current_buffer
);
130 current_buffer_
= buffers_
.begin();
131 current_buffer_offset_
= current_buffer_offset
;