OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/base/seekable_buffer.h" | 5 #include "media/base/seekable_buffer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "media/base/data_buffer.h" | 10 #include "media/base/data_buffer.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 buffers_.clear(); | 29 buffers_.clear(); |
30 current_buffer_ = buffers_.begin(); | 30 current_buffer_ = buffers_.begin(); |
31 current_buffer_offset_ = 0; | 31 current_buffer_offset_ = 0; |
32 backward_bytes_ = 0; | 32 backward_bytes_ = 0; |
33 forward_bytes_ = 0; | 33 forward_bytes_ = 0; |
34 current_time_ = kNoTimestamp(); | 34 current_time_ = kNoTimestamp(); |
35 } | 35 } |
36 | 36 |
37 size_t SeekableBuffer::Read(uint8* data, size_t size) { | 37 size_t SeekableBuffer::Read(uint8* data, size_t size) { |
38 DCHECK(data); | 38 DCHECK(data); |
39 return InternalRead(data, size, true); | 39 return InternalRead(data, size, true, 0); |
40 } | 40 } |
41 | 41 |
42 size_t SeekableBuffer::Peek(uint8* data, size_t size) { | 42 size_t SeekableBuffer::Peek(uint8* data, size_t size, size_t forward_offset) { |
43 DCHECK(data); | 43 DCHECK(data); |
44 return InternalRead(data, size, false); | 44 return InternalRead(data, size, false, forward_offset); |
45 } | 45 } |
46 | 46 |
47 bool SeekableBuffer::GetCurrentChunk(const uint8** data, size_t* size) const { | 47 bool SeekableBuffer::GetCurrentChunk(const uint8** data, size_t* size) const { |
48 BufferQueue::iterator current_buffer = current_buffer_; | 48 BufferQueue::iterator current_buffer = current_buffer_; |
49 size_t current_buffer_offset = current_buffer_offset_; | 49 size_t current_buffer_offset = current_buffer_offset_; |
50 // Advance position if we are in the end of the current buffer. | 50 // Advance position if we are in the end of the current buffer. |
51 while (current_buffer != buffers_.end() && | 51 while (current_buffer != buffers_.end() && |
52 current_buffer_offset >= (*current_buffer)->GetDataSize()) { | 52 current_buffer_offset >= (*current_buffer)->GetDataSize()) { |
53 ++current_buffer; | 53 ++current_buffer; |
54 current_buffer_offset = 0; | 54 current_buffer_offset = 0; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 return SeekBackward(-offset); | 106 return SeekBackward(-offset); |
107 return true; | 107 return true; |
108 } | 108 } |
109 | 109 |
110 bool SeekableBuffer::SeekForward(size_t size) { | 110 bool SeekableBuffer::SeekForward(size_t size) { |
111 // Perform seeking forward only if we have enough bytes in the queue. | 111 // Perform seeking forward only if we have enough bytes in the queue. |
112 if (size > forward_bytes_) | 112 if (size > forward_bytes_) |
113 return false; | 113 return false; |
114 | 114 |
115 // Do a read of |size| bytes. | 115 // Do a read of |size| bytes. |
116 size_t taken = InternalRead(NULL, size, true); | 116 size_t taken = InternalRead(NULL, size, true, 0); |
117 DCHECK_EQ(taken, size); | 117 DCHECK_EQ(taken, size); |
118 return true; | 118 return true; |
119 } | 119 } |
120 | 120 |
121 bool SeekableBuffer::SeekBackward(size_t size) { | 121 bool SeekableBuffer::SeekBackward(size_t size) { |
122 if (size > backward_bytes_) | 122 if (size > backward_bytes_) |
123 return false; | 123 return false; |
124 // Record the number of bytes taken. | 124 // Record the number of bytes taken. |
125 size_t taken = 0; | 125 size_t taken = 0; |
126 // Loop until we taken enough bytes and rewind by the desired |size|. | 126 // Loop until we taken enough bytes and rewind by the desired |size|. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 break; | 176 break; |
177 scoped_refptr<Buffer> buffer = *i; | 177 scoped_refptr<Buffer> buffer = *i; |
178 backward_bytes_ -= buffer->GetDataSize(); | 178 backward_bytes_ -= buffer->GetDataSize(); |
179 DCHECK_GE(backward_bytes_, 0u); | 179 DCHECK_GE(backward_bytes_, 0u); |
180 | 180 |
181 buffers_.erase(i); | 181 buffers_.erase(i); |
182 } | 182 } |
183 } | 183 } |
184 | 184 |
185 size_t SeekableBuffer::InternalRead(uint8* data, size_t size, | 185 size_t SeekableBuffer::InternalRead(uint8* data, size_t size, |
186 bool advance_position) { | 186 bool advance_position, |
| 187 size_t forward_offset) { |
187 // Counts how many bytes are actually read from the buffer queue. | 188 // Counts how many bytes are actually read from the buffer queue. |
188 size_t taken = 0; | 189 size_t taken = 0; |
189 | 190 |
190 BufferQueue::iterator current_buffer = current_buffer_; | 191 BufferQueue::iterator current_buffer = current_buffer_; |
191 size_t current_buffer_offset = current_buffer_offset_; | 192 size_t current_buffer_offset = current_buffer_offset_; |
192 | 193 |
| 194 size_t bytes_to_skip = forward_offset; |
193 while (taken < size) { | 195 while (taken < size) { |
194 // |current_buffer| is valid since the first time this buffer is appended | 196 // |current_buffer| is valid since the first time this buffer is appended |
195 // with data. | 197 // with data. |
196 if (current_buffer == buffers_.end()) | 198 if (current_buffer == buffers_.end()) |
197 break; | 199 break; |
198 | 200 |
199 scoped_refptr<Buffer> buffer = *current_buffer; | 201 scoped_refptr<Buffer> buffer = *current_buffer; |
200 | 202 |
201 // Find the right amount to copy from the current buffer referenced by | 203 size_t remaining_bytes_in_buffer = |
202 // |buffer|. We shall copy no more than |size| bytes in total and each | 204 buffer->GetDataSize() - current_buffer_offset; |
203 // single step copied no more than the current buffer size. | |
204 size_t copied = std::min(size - taken, | |
205 buffer->GetDataSize() - current_buffer_offset); | |
206 | 205 |
207 // |data| is NULL if we are seeking forward, so there's no need to copy. | 206 if (bytes_to_skip == 0) { |
208 if (data) | 207 // Find the right amount to copy from the current buffer referenced by |
209 memcpy(data + taken, buffer->GetData() + current_buffer_offset, copied); | 208 // |buffer|. We shall copy no more than |size| bytes in total and each |
| 209 // single step copied no more than the current buffer size. |
| 210 size_t copied = std::min(size - taken, remaining_bytes_in_buffer); |
210 | 211 |
211 // Increase total number of bytes copied, which regulates when to end this | 212 // |data| is NULL if we are seeking forward, so there's no need to copy. |
212 // loop. | 213 if (data) |
213 taken += copied; | 214 memcpy(data + taken, buffer->GetData() + current_buffer_offset, copied); |
214 | 215 |
215 // We have read |copied| bytes from the current buffer. Advances the offset. | 216 // Increase total number of bytes copied, which regulates when to end this |
216 current_buffer_offset += copied; | 217 // loop. |
| 218 taken += copied; |
| 219 |
| 220 // We have read |copied| bytes from the current buffer. Advances the |
| 221 // offset. |
| 222 current_buffer_offset += copied; |
| 223 } else { |
| 224 size_t skipped = std::min(remaining_bytes_in_buffer, bytes_to_skip); |
| 225 current_buffer_offset += skipped; |
| 226 bytes_to_skip -= skipped; |
| 227 } |
217 | 228 |
218 // The buffer has been consumed. | 229 // The buffer has been consumed. |
219 if (current_buffer_offset == buffer->GetDataSize()) { | 230 if (current_buffer_offset == buffer->GetDataSize()) { |
220 if (advance_position) { | 231 if (advance_position) { |
221 // Next buffer may not have timestamp, so we need to update current | 232 // Next buffer may not have timestamp, so we need to update current |
222 // timestamp before switching to the next buffer. | 233 // timestamp before switching to the next buffer. |
223 UpdateCurrentTime(current_buffer, current_buffer_offset); | 234 UpdateCurrentTime(current_buffer, current_buffer_offset); |
224 } | 235 } |
225 | 236 |
226 BufferQueue::iterator next = current_buffer; | 237 BufferQueue::iterator next = current_buffer; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 (*buffer)->GetTimestamp().InMicroseconds() > 0) { | 271 (*buffer)->GetTimestamp().InMicroseconds() > 0) { |
261 int64 time_offset = ((*buffer)->GetDuration().InMicroseconds() * | 272 int64 time_offset = ((*buffer)->GetDuration().InMicroseconds() * |
262 offset) / (*buffer)->GetDataSize(); | 273 offset) / (*buffer)->GetDataSize(); |
263 | 274 |
264 current_time_ = (*buffer)->GetTimestamp() + | 275 current_time_ = (*buffer)->GetTimestamp() + |
265 base::TimeDelta::FromMicroseconds(time_offset); | 276 base::TimeDelta::FromMicroseconds(time_offset); |
266 } | 277 } |
267 } | 278 } |
268 | 279 |
269 } // namespace media | 280 } // namespace media |
OLD | NEW |