Chromium Code Reviews| 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) { |
| 43 DCHECK(data); | 43 DCHECK(data); |
| 44 return InternalRead(data, size, false); | 44 return InternalRead(data, size, false, 0); |
|
acolwell GONE FROM CHROMIUM
2012/02/22 07:51:40
nit:How about removing DCHECK & just calling Peek(
vrk (LEFT CHROMIUM)
2012/02/23 20:33:06
D'oh! Yes, that would make sense, thanks :)
| |
| 45 } | |
| 46 | |
| 47 size_t SeekableBuffer::Peek(uint8* data, size_t size, size_t forward_offset) { | |
| 48 DCHECK(data); | |
| 49 return InternalRead(data, size, false, forward_offset); | |
| 45 } | 50 } |
| 46 | 51 |
| 47 bool SeekableBuffer::GetCurrentChunk(const uint8** data, size_t* size) const { | 52 bool SeekableBuffer::GetCurrentChunk(const uint8** data, size_t* size) const { |
| 48 BufferQueue::iterator current_buffer = current_buffer_; | 53 BufferQueue::iterator current_buffer = current_buffer_; |
| 49 size_t current_buffer_offset = current_buffer_offset_; | 54 size_t current_buffer_offset = current_buffer_offset_; |
| 50 // Advance position if we are in the end of the current buffer. | 55 // Advance position if we are in the end of the current buffer. |
| 51 while (current_buffer != buffers_.end() && | 56 while (current_buffer != buffers_.end() && |
| 52 current_buffer_offset >= (*current_buffer)->GetDataSize()) { | 57 current_buffer_offset >= (*current_buffer)->GetDataSize()) { |
| 53 ++current_buffer; | 58 ++current_buffer; |
| 54 current_buffer_offset = 0; | 59 current_buffer_offset = 0; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 return SeekBackward(-offset); | 111 return SeekBackward(-offset); |
| 107 return true; | 112 return true; |
| 108 } | 113 } |
| 109 | 114 |
| 110 bool SeekableBuffer::SeekForward(size_t size) { | 115 bool SeekableBuffer::SeekForward(size_t size) { |
| 111 // Perform seeking forward only if we have enough bytes in the queue. | 116 // Perform seeking forward only if we have enough bytes in the queue. |
| 112 if (size > forward_bytes_) | 117 if (size > forward_bytes_) |
| 113 return false; | 118 return false; |
| 114 | 119 |
| 115 // Do a read of |size| bytes. | 120 // Do a read of |size| bytes. |
| 116 size_t taken = InternalRead(NULL, size, true); | 121 size_t taken = InternalRead(NULL, size, true, 0); |
| 117 DCHECK_EQ(taken, size); | 122 DCHECK_EQ(taken, size); |
| 118 return true; | 123 return true; |
| 119 } | 124 } |
| 120 | 125 |
| 121 bool SeekableBuffer::SeekBackward(size_t size) { | 126 bool SeekableBuffer::SeekBackward(size_t size) { |
| 122 if (size > backward_bytes_) | 127 if (size > backward_bytes_) |
| 123 return false; | 128 return false; |
| 124 // Record the number of bytes taken. | 129 // Record the number of bytes taken. |
| 125 size_t taken = 0; | 130 size_t taken = 0; |
| 126 // Loop until we taken enough bytes and rewind by the desired |size|. | 131 // 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; | 181 break; |
| 177 scoped_refptr<Buffer> buffer = *i; | 182 scoped_refptr<Buffer> buffer = *i; |
| 178 backward_bytes_ -= buffer->GetDataSize(); | 183 backward_bytes_ -= buffer->GetDataSize(); |
| 179 DCHECK_GE(backward_bytes_, 0u); | 184 DCHECK_GE(backward_bytes_, 0u); |
| 180 | 185 |
| 181 buffers_.erase(i); | 186 buffers_.erase(i); |
| 182 } | 187 } |
| 183 } | 188 } |
| 184 | 189 |
| 185 size_t SeekableBuffer::InternalRead(uint8* data, size_t size, | 190 size_t SeekableBuffer::InternalRead(uint8* data, size_t size, |
| 186 bool advance_position) { | 191 bool advance_position, |
| 192 size_t forward_offset) { | |
| 187 // Counts how many bytes are actually read from the buffer queue. | 193 // Counts how many bytes are actually read from the buffer queue. |
| 188 size_t taken = 0; | 194 size_t taken = 0; |
| 189 | 195 |
| 190 BufferQueue::iterator current_buffer = current_buffer_; | 196 BufferQueue::iterator current_buffer = current_buffer_; |
| 191 size_t current_buffer_offset = current_buffer_offset_; | 197 size_t current_buffer_offset = current_buffer_offset_; |
| 192 | 198 |
| 199 size_t bytes_to_skip = forward_offset; | |
| 193 while (taken < size) { | 200 while (taken < size) { |
| 194 // |current_buffer| is valid since the first time this buffer is appended | 201 // |current_buffer| is valid since the first time this buffer is appended |
| 195 // with data. | 202 // with data. |
| 196 if (current_buffer == buffers_.end()) | 203 if (current_buffer == buffers_.end()) |
| 197 break; | 204 break; |
| 198 | 205 |
| 199 scoped_refptr<Buffer> buffer = *current_buffer; | 206 scoped_refptr<Buffer> buffer = *current_buffer; |
| 200 | 207 |
| 201 // Find the right amount to copy from the current buffer referenced by | 208 size_t remaining_bytes_in_buffer = |
| 202 // |buffer|. We shall copy no more than |size| bytes in total and each | 209 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 | 210 |
| 207 // |data| is NULL if we are seeking forward, so there's no need to copy. | 211 if (bytes_to_skip == 0) { |
| 208 if (data) | 212 // Find the right amount to copy from the current buffer referenced by |
| 209 memcpy(data + taken, buffer->GetData() + current_buffer_offset, copied); | 213 // |buffer|. We shall copy no more than |size| bytes in total and each |
| 214 // single step copied no more than the current buffer size. | |
| 215 size_t copied = std::min(size - taken, remaining_bytes_in_buffer); | |
| 210 | 216 |
| 211 // Increase total number of bytes copied, which regulates when to end this | 217 // |data| is NULL if we are seeking forward, so there's no need to copy. |
| 212 // loop. | 218 if (data) |
| 213 taken += copied; | 219 memcpy(data + taken, buffer->GetData() + current_buffer_offset, copied); |
| 214 | 220 |
| 215 // We have read |copied| bytes from the current buffer. Advances the offset. | 221 // Increase total number of bytes copied, which regulates when to end this |
| 216 current_buffer_offset += copied; | 222 // loop. |
| 223 taken += copied; | |
| 224 | |
| 225 // We have read |copied| bytes from the current buffer. Advances the | |
| 226 // offset. | |
| 227 current_buffer_offset += copied; | |
| 228 } else { | |
| 229 size_t skipped = std::min(remaining_bytes_in_buffer, bytes_to_skip); | |
| 230 current_buffer_offset += skipped; | |
| 231 bytes_to_skip -= skipped; | |
| 232 } | |
| 217 | 233 |
| 218 // The buffer has been consumed. | 234 // The buffer has been consumed. |
| 219 if (current_buffer_offset == buffer->GetDataSize()) { | 235 if (current_buffer_offset == buffer->GetDataSize()) { |
| 220 if (advance_position) { | 236 if (advance_position) { |
| 221 // Next buffer may not have timestamp, so we need to update current | 237 // Next buffer may not have timestamp, so we need to update current |
| 222 // timestamp before switching to the next buffer. | 238 // timestamp before switching to the next buffer. |
| 223 UpdateCurrentTime(current_buffer, current_buffer_offset); | 239 UpdateCurrentTime(current_buffer, current_buffer_offset); |
| 224 } | 240 } |
| 225 | 241 |
| 226 BufferQueue::iterator next = current_buffer; | 242 BufferQueue::iterator next = current_buffer; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 260 (*buffer)->GetTimestamp().InMicroseconds() > 0) { | 276 (*buffer)->GetTimestamp().InMicroseconds() > 0) { |
| 261 int64 time_offset = ((*buffer)->GetDuration().InMicroseconds() * | 277 int64 time_offset = ((*buffer)->GetDuration().InMicroseconds() * |
| 262 offset) / (*buffer)->GetDataSize(); | 278 offset) / (*buffer)->GetDataSize(); |
| 263 | 279 |
| 264 current_time_ = (*buffer)->GetTimestamp() + | 280 current_time_ = (*buffer)->GetTimestamp() + |
| 265 base::TimeDelta::FromMicroseconds(time_offset); | 281 base::TimeDelta::FromMicroseconds(time_offset); |
| 266 } | 282 } |
| 267 } | 283 } |
| 268 | 284 |
| 269 } // namespace media | 285 } // namespace media |
| OLD | NEW |