| 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 |