Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Side by Side Diff: media/base/audio_buffer_queue.cc

Issue 17112016: Add new class AudioBufferQueue. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/base/audio_buffer_queue.h ('k') | media/base/audio_buffer_queue_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "media/base/audio_buffer_queue.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10 #include "media/base/audio_bus.h"
11 #include "media/base/buffers.h"
12
13 namespace media {
14
15 AudioBufferQueue::AudioBufferQueue() { Clear(); }
16 AudioBufferQueue::~AudioBufferQueue() {}
17
18 void AudioBufferQueue::Clear() {
19 buffers_.clear();
20 current_buffer_ = buffers_.begin();
21 current_buffer_offset_ = 0;
22 frames_ = 0;
23 current_time_ = kNoTimestamp();
24 }
25
26 void AudioBufferQueue::Append(const scoped_refptr<AudioBuffer>& buffer_in) {
27 // If we have just written the first buffer, update |current_time_| to be the
28 // start time.
29 if (buffers_.empty()) {
30 DCHECK_EQ(frames_, 0);
31 current_time_ = buffer_in->timestamp();
32 }
33
34 // Add the buffer to the queue. Inserting into deque invalidates all
35 // iterators, so point to the first buffer.
36 buffers_.push_back(buffer_in);
37 current_buffer_ = buffers_.begin();
38
39 // Update the |frames_| counter since we have added frames.
40 frames_ += buffer_in->frame_count();
41 CHECK_GT(frames_, 0); // make sure it doesn't overflow.
42 }
43
44 int AudioBufferQueue::ReadFrames(int frames, AudioBus* dest) {
45 DCHECK_GE(dest->frames(), frames);
46 return InternalRead(frames, true, 0, dest);
47 }
48
49 int AudioBufferQueue::PeekFrames(int frames,
50 int forward_offset,
51 AudioBus* dest) {
52 DCHECK_GE(dest->frames(), frames);
53 return InternalRead(frames, false, forward_offset, dest);
54 }
55
56 void AudioBufferQueue::SeekFrames(int frames) {
57 // Perform seek only if we have enough bytes in the queue.
58 CHECK_LE(frames, frames_);
59 int taken = InternalRead(frames, true, 0, NULL);
60 DCHECK_EQ(taken, frames);
61 }
62
63 int AudioBufferQueue::InternalRead(int frames,
64 bool advance_position,
65 int forward_offset,
66 AudioBus* dest) {
67 // Counts how many frames are actually read from the buffer queue.
68 int taken = 0;
69 BufferQueue::iterator current_buffer = current_buffer_;
70 int current_buffer_offset = current_buffer_offset_;
71
72 int frames_to_skip = forward_offset;
73 while (taken < frames) {
74 // |current_buffer| is valid since the first time this buffer is appended
75 // with data. Make sure there is data to be processed.
76 if (current_buffer == buffers_.end())
77 break;
78
79 scoped_refptr<AudioBuffer> buffer = *current_buffer;
80
81 int remaining_frames_in_buffer =
82 buffer->frame_count() - current_buffer_offset;
83
84 if (frames_to_skip > 0) {
85 // If there are frames to skip, do it first. May need to skip into
86 // subsequent buffers.
87 int skipped = std::min(remaining_frames_in_buffer, frames_to_skip);
88 current_buffer_offset += skipped;
89 frames_to_skip -= skipped;
90 } else {
91 // Find the right amount to copy from the current buffer. We shall copy no
92 // more than |frames| frames in total and each single step copies no more
93 // than the current buffer size.
94 int copied = std::min(frames - taken, remaining_frames_in_buffer);
95
96 // if |dest| is NULL, there's no need to copy.
97 if (dest)
98 buffer->ReadFrames(copied, current_buffer_offset, taken, dest);
99
100 // Increase total number of frames copied, which regulates when to end
101 // this loop.
102 taken += copied;
103
104 // We have read |copied| frames from the current buffer. Advance the
105 // offset.
106 current_buffer_offset += copied;
107 }
108
109 // Has the buffer has been consumed?
110 if (current_buffer_offset == buffer->frame_count()) {
111 if (advance_position) {
112 // Next buffer may not have timestamp, so we need to update current
113 // timestamp before switching to the next buffer.
114 UpdateCurrentTime(current_buffer, current_buffer_offset);
115 }
116
117 // If we are at the last buffer, no more data to be copied, so stop.
118 BufferQueue::iterator next = current_buffer + 1;
119 if (next == buffers_.end())
120 break;
121
122 // Advances the iterator.
123 current_buffer = next;
124 current_buffer_offset = 0;
125 }
126 }
127
128 if (advance_position) {
129 // Update the appropriate values since |taken| frames have been copied out.
130 frames_ -= taken;
131 DCHECK_GE(frames_, 0);
132 DCHECK(current_buffer_ != buffers_.end() || frames_ == 0);
133
134 current_buffer_ = current_buffer;
135 current_buffer_offset_ = current_buffer_offset;
136
137 UpdateCurrentTime(current_buffer_, current_buffer_offset_);
138
139 // Remove any buffers before the current buffer as there is no going
140 // backwards.
141 buffers_.erase(buffers_.begin(), current_buffer_);
142 }
143
144 return taken;
145 }
146
147 void AudioBufferQueue::UpdateCurrentTime(BufferQueue::iterator buffer,
148 int offset) {
149 if (buffer != buffers_.end() && (*buffer)->timestamp() != kNoTimestamp()) {
150 double time_offset = ((*buffer)->duration().InMicroseconds() * offset) /
151 static_cast<double>((*buffer)->frame_count());
152 current_time_ =
153 (*buffer)->timestamp() + base::TimeDelta::FromMicroseconds(
154 static_cast<int64>(time_offset + 0.5));
155 }
156 }
157
158 } // namespace media
OLDNEW
« no previous file with comments | « media/base/audio_buffer_queue.h ('k') | media/base/audio_buffer_queue_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698