15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/seekable_buffer.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/data_buffer.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSeekableBuffer::SeekableBuffer(int backward_capacity, int forward_capacity) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : current_buffer_offset_(0), 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backward_capacity_(backward_capacity), 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backward_bytes_(0), 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) forward_capacity_(forward_capacity), 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) forward_bytes_(0), 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_time_(kNoTimestamp()) { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer_ = buffers_.begin(); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SeekableBuffer::~SeekableBuffer() { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SeekableBuffer::Clear() { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffers_.clear(); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer_ = buffers_.begin(); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer_offset_ = 0; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backward_bytes_ = 0; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) forward_bytes_ = 0; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_time_ = kNoTimestamp(); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SeekableBuffer::Read(uint8* data, int size) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InternalRead(data, size, true, 0); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SeekableBuffer::Peek(uint8* data, int size, int forward_offset) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InternalRead(data, size, false, forward_offset); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SeekableBuffer::GetCurrentChunk(const uint8** data, int* size) const { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BufferQueue::iterator current_buffer = current_buffer_; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int current_buffer_offset = current_buffer_offset_; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Advance position if we are in the end of the current buffer. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (current_buffer != buffers_.end() && 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch current_buffer_offset >= (*current_buffer)->data_size()) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++current_buffer; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer_offset = 0; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_buffer == buffers_.end()) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *data = (*current_buffer)->data() + current_buffer_offset; 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *size = (*current_buffer)->data_size() - current_buffer_offset; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SeekableBuffer::Append(const scoped_refptr<DataBuffer>& buffer_in) { 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (buffers_.empty() && buffer_in->timestamp() != kNoTimestamp()) { 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch current_time_ = buffer_in->timestamp(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since the forward capacity is only used to check the criteria for buffer 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // full, we always append data to the buffer. 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffers_.push_back(buffer_in); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // After we have written the first buffer, update |current_buffer_| to point 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to it. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_buffer_ == buffers_.end()) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0, forward_bytes_); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer_ = buffers_.begin(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the |forward_bytes_| counter since we have more bytes. 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch forward_bytes_ += buffer_in->data_size(); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Advise the user to stop append if the amount of forward bytes exceeds 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the forward capacity. A false return value means the user should stop 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appending more data to this buffer. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (forward_bytes_ >= forward_capacity_) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SeekableBuffer::Append(const uint8* data, int size) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size > 0) { 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<DataBuffer> data_buffer = DataBuffer::CopyFrom(data, size); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Append(data_buffer); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return true if we have forward capacity. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return forward_bytes_ < forward_capacity_; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SeekableBuffer::Seek(int32 offset) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (offset > 0) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SeekForward(offset); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (offset < 0) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SeekBackward(-offset); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SeekableBuffer::SeekForward(int size) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Perform seeking forward only if we have enough bytes in the queue. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size > forward_bytes_) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do a read of |size| bytes. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int taken = InternalRead(NULL, size, true, 0); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(taken, size); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SeekableBuffer::SeekBackward(int size) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size > backward_bytes_) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record the number of bytes taken. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int taken = 0; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Loop until we taken enough bytes and rewind by the desired |size|. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (taken < size) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |current_buffer_| can never be invalid when we are in this loop. It can 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only be invalid before any data is appended. The invalid case should be 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handled by checks before we enter this loop. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(current_buffer_ != buffers_.end()); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We try to consume at most |size| bytes in the backward direction. We also 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have to account for the offset we are in the current buffer, so take the 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // minimum between the two to determine the amount of bytes to take from the 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current buffer. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int consumed = std::min(size - taken, current_buffer_offset_); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Decreases the offset in the current buffer since we are rewinding. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer_offset_ -= consumed; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Increase the amount of bytes taken in the backward direction. This 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // determines when to stop the loop. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) taken += consumed; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Forward bytes increases and backward bytes decreases by the amount 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // consumed in the current buffer. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) forward_bytes_ += consumed; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backward_bytes_ -= consumed; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(backward_bytes_, 0); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The current buffer pointed by current iterator has been consumed. Move 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the iterator backward so it points to the previous buffer. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_buffer_offset_ == 0) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_buffer_ == buffers_.begin()) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move the iterator backward. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --current_buffer_; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the offset into the current buffer to be the buffer size as we 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are preparing for rewind for next iteration. 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch current_buffer_offset_ = (*current_buffer_)->data_size(); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateCurrentTime(current_buffer_, current_buffer_offset_); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(taken, size); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SeekableBuffer::EvictBackwardBuffers() { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Advances the iterator until we hit the current pointer. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (backward_bytes_ > backward_capacity_) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BufferQueue::iterator i = buffers_.begin(); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == current_buffer_) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<DataBuffer> buffer = *i; 175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch backward_bytes_ -= buffer->data_size(); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(backward_bytes_, 0); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffers_.erase(i); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SeekableBuffer::InternalRead(uint8* data, int size, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool advance_position, 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int forward_offset) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Counts how many bytes are actually read from the buffer queue. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int taken = 0; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BufferQueue::iterator current_buffer = current_buffer_; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int current_buffer_offset = current_buffer_offset_; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_to_skip = forward_offset; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (taken < size) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |current_buffer| is valid since the first time this buffer is appended 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with data. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_buffer == buffers_.end()) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<DataBuffer> buffer = *current_buffer; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int remaining_bytes_in_buffer = 201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch buffer->data_size() - current_buffer_offset; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_to_skip == 0) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the right amount to copy from the current buffer referenced by 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |buffer|. We shall copy no more than |size| bytes in total and each 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // single step copied no more than the current buffer size. 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int copied = std::min(size - taken, remaining_bytes_in_buffer); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |data| is NULL if we are seeking forward, so there's no need to copy. 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data) 211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch memcpy(data + taken, buffer->data() + current_buffer_offset, copied); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Increase total number of bytes copied, which regulates when to end this 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loop. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) taken += copied; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have read |copied| bytes from the current buffer. Advances the 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // offset. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer_offset += copied; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int skipped = std::min(remaining_bytes_in_buffer, bytes_to_skip); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer_offset += skipped; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_to_skip -= skipped; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The buffer has been consumed. 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (current_buffer_offset == buffer->data_size()) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (advance_position) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Next buffer may not have timestamp, so we need to update current 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // timestamp before switching to the next buffer. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateCurrentTime(current_buffer, current_buffer_offset); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BufferQueue::iterator next = current_buffer; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++next; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are at the last buffer, don't advance. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next == buffers_.end()) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Advances the iterator. 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer = next; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer_offset = 0; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (advance_position) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have less forward bytes and more backward bytes. Updates these 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // counters by |taken|. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) forward_bytes_ -= taken; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backward_bytes_ += taken; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(forward_bytes_, 0); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(current_buffer_ != buffers_.end() || forward_bytes_ == 0); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer_ = current_buffer; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_buffer_offset_ = current_buffer_offset; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateCurrentTime(current_buffer_, current_buffer_offset_); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EvictBackwardBuffers(); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return taken; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SeekableBuffer::UpdateCurrentTime(BufferQueue::iterator buffer, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int offset) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Garbage values are unavoidable, so this check will remain. 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (buffer != buffers_.end() && 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*buffer)->timestamp() != kNoTimestamp()) { 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int64 time_offset = ((*buffer)->duration().InMicroseconds() * offset) / 270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*buffer)->data_size(); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch current_time_ = (*buffer)->timestamp() + 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::TimeDelta::FromMicroseconds(time_offset); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 278