Index: content/browser/renderer_host/media/video_capture_buffer_pool.cc |
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool.cc b/content/browser/renderer_host/media/video_capture_buffer_pool.cc |
index f6486a5405128c6006329a2462a794fbf7c4a38c..557defa7c527738f2b80f15a3939edbdfac6f5ea 100644 |
--- a/content/browser/renderer_host/media/video_capture_buffer_pool.cc |
+++ b/content/browser/renderer_host/media/video_capture_buffer_pool.cc |
@@ -42,6 +42,22 @@ base::SharedMemoryHandle VideoCaptureBufferPool::ShareToProcess( |
return remote_handle; |
} |
+bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id, |
+ void** memory, |
+ size_t* size) { |
+ base::AutoLock lock(lock_); |
+ |
+ Buffer* buffer = GetBuffer(buffer_id); |
+ if (!buffer) { |
+ NOTREACHED() << "Invalid buffer_id."; |
+ return false; |
+ } |
+ |
+ *memory = buffer->shared_memory.memory(); |
+ *size = buffer->shared_memory.mapped_size(); |
+ return true; |
+} |
+ |
int VideoCaptureBufferPool::ReserveForProducer(size_t size, |
int* buffer_id_to_drop) { |
base::AutoLock lock(lock_); |
@@ -91,10 +107,10 @@ void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id, |
} |
int VideoCaptureBufferPool::RecognizeReservedBuffer( |
- base::SharedMemoryHandle maybe_belongs_to_pool) { |
+ const void* maybe_belongs_to_pool) { |
base::AutoLock lock(lock_); |
for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); it++) { |
- if (it->second->shared_memory.handle() == maybe_belongs_to_pool) { |
+ if (it->second->shared_memory.memory() == maybe_belongs_to_pool) { |
DCHECK(it->second->held_by_producer); |
return it->first; |
} |
@@ -102,58 +118,23 @@ int VideoCaptureBufferPool::RecognizeReservedBuffer( |
return kInvalidId; // Buffer is not from our pool. |
} |
-scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveI420VideoFrame( |
- const gfx::Size& size, |
- int rotation, |
- int* buffer_id_to_drop) { |
- base::AutoLock lock(lock_); |
- |
- size_t frame_bytes = |
- media::VideoFrame::AllocationSize(media::VideoFrame::I420, size); |
- |
- int buffer_id = ReserveForProducerInternal(frame_bytes, buffer_id_to_drop); |
- if (buffer_id == kInvalidId) |
- return NULL; |
- |
- base::Closure disposal_handler = base::Bind( |
- &VideoCaptureBufferPool::RelinquishProducerReservation, |
- this, |
- buffer_id); |
- |
- Buffer* buffer = GetBuffer(buffer_id); |
- // Wrap the buffer in a VideoFrame container. |
- scoped_refptr<media::VideoFrame> frame = |
- media::VideoFrame::WrapExternalSharedMemory( |
- media::VideoFrame::I420, |
- size, |
- gfx::Rect(size), |
- size, |
- static_cast<uint8*>(buffer->shared_memory.memory()), |
- frame_bytes, |
- buffer->shared_memory.handle(), |
- base::TimeDelta(), |
- disposal_handler); |
- |
- if (buffer->rotation != rotation) { |
- // TODO(jiayl): Generalize the |rotation| mechanism. |
- media::FillYUV(frame.get(), 0, 128, 128); |
- buffer->rotation = rotation; |
- } |
- |
- return frame; |
-} |
- |
VideoCaptureBufferPool::Buffer::Buffer() |
- : rotation(0), |
- held_by_producer(false), |
- consumer_hold_count(0) {} |
+ : held_by_producer(false), consumer_hold_count(0) {} |
int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size, |
int* buffer_id_to_drop) { |
lock_.AssertAcquired(); |
- // Look for a buffer that's allocated, big enough, and not in use. |
+ // Even zero-sized placeholder buffers need some memory allocation, so that |
+ // RecognizeReservedBuffer() can have some pointer to recognize. |
+ if (!size) |
+ size = 1; |
+ |
+ // Look for a buffer that's allocated, big enough, and not in use. Track the |
+ // largest one that's not big enough, in case we have to reallocate a buffer. |
*buffer_id_to_drop = kInvalidId; |
+ size_t realloc_size = 0; |
+ BufferMap::iterator realloc = buffers_.end(); |
for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); it++) { |
Buffer* buffer = it->second; |
if (!buffer->consumer_hold_count && !buffer->held_by_producer) { |
@@ -162,35 +143,33 @@ int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size, |
buffer->held_by_producer = true; |
return it->first; |
} |
+ if (buffer->shared_memory.requested_size() > realloc_size) { |
+ realloc_size = buffer->shared_memory.requested_size(); |
+ realloc = it; |
+ } |
} |
} |
- // Look for a buffer that's not in use, that we can reallocate. |
- for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); it++) { |
- Buffer* buffer = it->second; |
- if (!buffer->consumer_hold_count && !buffer->held_by_producer) { |
- // Existing buffer is too small. Free it so we can allocate a new one |
- // after the loop. |
- *buffer_id_to_drop = it->first; |
- buffers_.erase(it); |
- delete buffer; |
- break; |
- } |
- } |
- |
- // If possible, grow the pool by creating a new buffer. |
- if (static_cast<int>(buffers_.size()) < count_) { |
- int buffer_id = next_buffer_id_++; |
- scoped_ptr<Buffer> buffer(new Buffer()); |
- if (!buffer->shared_memory.CreateAndMapAnonymous(size)) |
+ // Preferentially grow the pool by creating a new buffer. If we're at maximum |
+ // size, then reallocate by deleting an existing one instead. |
+ if (buffers_.size() == static_cast<size_t>(count_)) { |
+ if (realloc == buffers_.end()) { |
+ // We're out of space, and can't find an unused buffer to reallocate. |
return kInvalidId; |
- buffer->held_by_producer = true; |
- buffers_[buffer_id] = buffer.release(); |
- return buffer_id; |
+ } |
+ *buffer_id_to_drop = realloc->first; |
+ delete realloc->second; |
+ buffers_.erase(realloc); |
} |
- // The pool is at its size limit, and all buffers are in use. |
- return kInvalidId; |
+ // Create the new buffer. |
+ int buffer_id = next_buffer_id_++; |
+ scoped_ptr<Buffer> buffer(new Buffer()); |
+ if (!buffer->shared_memory.CreateAndMapAnonymous(size)) |
+ return kInvalidId; |
+ buffer->held_by_producer = true; |
+ buffers_[buffer_id] = buffer.release(); |
+ return buffer_id; |
} |
VideoCaptureBufferPool::Buffer* VideoCaptureBufferPool::GetBuffer( |