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

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
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 first_buffer_ = true;
25 }
26
27 void AudioBufferQueue::Append(const scoped_refptr<AudioBuffer>& buffer_in) {
28 buffers_.push_back(buffer_in);
29
30 // Inserting into deque invalidates all iterators, so point to the first
31 // buffer.
32 current_buffer_ = buffers_.begin();
33
34 // If we have just written the first buffer, update |current_time_| to be the
35 // start time.
36 if (first_buffer_) {
DaleCurtis 2013/06/20 22:08:59 Is it enough to just check if current_time_ is kNo
jrummell 2013/06/20 23:28:58 I don't know if there are cases where you can push
37 DCHECK_EQ(frames_, 0);
38 current_time_ = buffer_in->timestamp();
39 first_buffer_ = false;
40 }
41
42 // Update the |frames_| counter since we have added frames.
43 frames_ += buffer_in->frame_count();
DaleCurtis 2013/06/20 22:08:59 It's possible this could overflow, maybe CHECK_GT(
jrummell 2013/06/20 23:28:58 Done.
44 }
45
46 int AudioBufferQueue::ReadFrames(int frames, AudioBus* dest) {
47 DCHECK_GE(dest->frames(), frames);
48 return InternalRead(frames, true, 0, dest);
49 }
50
51 int AudioBufferQueue::PeekFrames(int frames,
52 int forward_offset,
scherkus (not reviewing) 2013/06/20 22:05:15 fix indent
DaleCurtis 2013/06/20 22:08:59 Fix indent.
jrummell 2013/06/20 23:28:58 Done.
53 AudioBus* dest) {
54 DCHECK_GE(dest->frames(), frames);
55 return InternalRead(frames, false, forward_offset, dest);
56 }
57
58 void AudioBufferQueue::SeekFrames(int frames) {
59 // Perform seek only if we have enough bytes in the queue.
60 CHECK_LE(frames, frames_);
61 int taken = InternalRead(frames, true, 0, NULL);
62 DCHECK_EQ(taken, frames);
63 }
64
65 int AudioBufferQueue::InternalRead(int frames,
66 bool advance_position,
scherkus (not reviewing) 2013/06/20 22:05:15 fix indent
DaleCurtis 2013/06/20 22:08:59 Fix indent.
jrummell 2013/06/20 23:28:58 Done.
67 int forward_offset,
68 AudioBus* dest) {
69 // Counts how many frames are actually read from the buffer queue.
70 int taken = 0;
71 BufferQueue::iterator current_buffer = current_buffer_;
72 int current_buffer_offset = current_buffer_offset_;
73
74 int frames_to_skip = forward_offset;
75 while (taken < frames) {
76 // |current_buffer| is valid since the first time this buffer is appended
77 // with data. Make sure there is data to be processed.
78 if (current_buffer == buffers_.end())
79 break;
80
81 scoped_refptr<AudioBuffer> buffer = *current_buffer;
82
83 int remaining_frames_in_buffer =
84 buffer->frame_count() - current_buffer_offset;
85
86 if (frames_to_skip > 0) {
87 // If there are frames to skip, do it first. May need to skip into
88 // subsequent buffers.
89 int skipped = std::min(remaining_frames_in_buffer, frames_to_skip);
90 current_buffer_offset += skipped;
91 frames_to_skip -= skipped;
92 } else {
93 // Find the right amount to copy from the current buffer. We shall copy no
94 // more than |frames| frames in total and each single step copies no more
95 // than the current buffer size.
96 int copied = std::min(frames - taken, remaining_frames_in_buffer);
97
98 // if |dest| is NULL, there's no need to copy.
99 if (dest)
100 buffer->ReadFrames(copied, current_buffer_offset, taken, dest);
101
102 // Increase total number of frames copied, which regulates when to end
103 // this loop.
104 taken += copied;
105
106 // We have read |copied| frames from the current buffer. Advance the
107 // offset.
108 current_buffer_offset += copied;
109 }
110
111 // Has the buffer has been consumed?
112 if (current_buffer_offset == buffer->frame_count()) {
113 if (advance_position) {
114 // Next buffer may not have timestamp, so we need to update current
115 // timestamp before switching to the next buffer.
116 UpdateCurrentTime(current_buffer, current_buffer_offset);
117 }
118
119 BufferQueue::iterator next = current_buffer;
DaleCurtis 2013/06/20 22:08:59 Does current_buffer + 1 work?
jrummell 2013/06/20 23:28:58 Done.
120 ++next;
121 // If we are at the last buffer, no more data to be copied, so stop.
122 if (next == buffers_.end())
123 break;
124
125 // Advances the iterator.
126 current_buffer = next;
127 current_buffer_offset = 0;
128 }
129 }
130
131 if (advance_position) {
132 // Update the appropriate values since |taken| frames have been copied out.
133 frames_ -= taken;
134 DCHECK_GE(frames_, 0);
135 DCHECK(current_buffer_ != buffers_.end() || frames_ == 0);
136
137 current_buffer_ = current_buffer;
138 current_buffer_offset_ = current_buffer_offset;
139
140 UpdateCurrentTime(current_buffer_, current_buffer_offset_);
141
142 // Remove any buffers before the current buffer as there is no going
143 // backwards.
144 buffers_.erase(buffers_.begin(), current_buffer_);
DaleCurtis 2013/06/20 22:08:59 Did you figure out if this invalidates current_buf
jrummell 2013/06/20 23:28:58 According to the stackoverflow page referenced in
145 }
146
147 return taken;
148 }
149
150 void AudioBufferQueue::UpdateCurrentTime(BufferQueue::iterator buffer,
151 int offset) {
scherkus (not reviewing) 2013/06/20 22:05:15 fix indent
jrummell 2013/06/20 23:28:58 Done.
152 if (buffer != buffers_.end() && (*buffer)->timestamp() != kNoTimestamp()) {
153 double time_offset = ((*buffer)->duration().InMicroseconds() * offset) /
154 static_cast<double>((*buffer)->frame_count());
155 current_time_ =
156 (*buffer)->timestamp() + base::TimeDelta::FromMicroseconds(
157 static_cast<int64>(time_offset + 0.5));
158 }
159 }
160
161 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698