Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 | |
| OLD | NEW |