Chromium Code Reviews| 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 3e30834feb2ca8a17788ddd94cf3b0ade2147eb9..4be4db8fef4fb9252a5fa7be9860cad57bcb7859 100644 |
| --- a/content/browser/renderer_host/media/video_capture_buffer_pool.cc |
| +++ b/content/browser/renderer_host/media/video_capture_buffer_pool.cc |
| @@ -7,71 +7,51 @@ |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/logging.h" |
| +#include "base/stl_util.h" |
| #include "media/base/video_frame.h" |
| #include "media/base/video_util.h" |
| namespace content { |
| -VideoCaptureBufferPool::VideoCaptureBufferPool(size_t size, int count) |
| - : size_(size), |
| +VideoCaptureBufferPool::VideoCaptureBufferPool(int count) |
| + : next_buffer_id_(0), |
| count_(count) { |
| } |
| VideoCaptureBufferPool::~VideoCaptureBufferPool() { |
| -} |
| - |
| -bool VideoCaptureBufferPool::Allocate() { |
| - base::AutoLock lock(lock_); |
| - DCHECK(!IsAllocated()); |
| - buffers_.resize(count_); |
| - for (int buffer_id = 0; buffer_id < count(); ++buffer_id) { |
| - Buffer* buffer = new Buffer(); |
| - buffers_[buffer_id] = buffer; |
| - if (!buffer->shared_memory.CreateAndMapAnonymous(GetMemorySize())) |
| - return false; |
| - } |
| - return true; |
| + STLDeleteValues(&buffers_); |
| } |
| base::SharedMemoryHandle VideoCaptureBufferPool::ShareToProcess( |
| int buffer_id, |
| - base::ProcessHandle process_handle) { |
| + base::ProcessHandle process_handle, |
| + size_t* memory_size) { |
| base::AutoLock lock(lock_); |
| - DCHECK(IsAllocated()); |
| - DCHECK(buffer_id >= 0); |
| - DCHECK(buffer_id < count_); |
| - Buffer* buffer = buffers_[buffer_id]; |
| + |
| + Buffer* buffer = GetBuffer(buffer_id); |
| + if (!buffer) { |
| + NOTREACHED() << "Invalid buffer_id."; |
| + return base::SharedMemory::NULLHandle(); |
| + } |
| base::SharedMemoryHandle remote_handle; |
| buffer->shared_memory.ShareToProcess(process_handle, &remote_handle); |
| + *memory_size = buffer->shared_memory.requested_size(); |
| return remote_handle; |
| } |
| -base::SharedMemoryHandle VideoCaptureBufferPool::GetHandle(int buffer_id) { |
| +int VideoCaptureBufferPool::ReserveForProducer(size_t size, |
| + int* buffer_id_to_drop) { |
| base::AutoLock lock(lock_); |
| - DCHECK(IsAllocated()); |
| - DCHECK(buffer_id >= 0); |
| - DCHECK(buffer_id < count_); |
| - return buffers_[buffer_id]->shared_memory.handle(); |
| -} |
| - |
| -void* VideoCaptureBufferPool::GetMemory(int buffer_id) { |
| - base::AutoLock lock(lock_); |
| - DCHECK(IsAllocated()); |
| - DCHECK(buffer_id >= 0); |
| - DCHECK(buffer_id < count_); |
| - return buffers_[buffer_id]->shared_memory.memory(); |
| -} |
| - |
| -int VideoCaptureBufferPool::ReserveForProducer() { |
| - base::AutoLock lock(lock_); |
| - return ReserveForProducerInternal(); |
| + return ReserveForProducerInternal(size, buffer_id_to_drop); |
|
Ami GONE FROM CHROMIUM
2013/10/04 00:24:15
nit: s/Internal/_Locked/ ?
ncarter (slow)
2013/10/16 02:08:40
This name isn't introduced by this CL. I'm fine wi
|
| } |
| void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) { |
| base::AutoLock lock(lock_); |
| - DCHECK(buffer_id >= 0); |
| - DCHECK(buffer_id < count()); |
| - Buffer* buffer = buffers_[buffer_id]; |
| + Buffer* buffer = GetBuffer(buffer_id); |
| + if (!buffer) { |
| + NOTREACHED() << "Invalid buffer_id."; |
| + return; |
| + } |
| DCHECK(buffer->held_by_producer); |
| buffer->held_by_producer = false; |
| } |
| @@ -80,65 +60,56 @@ void VideoCaptureBufferPool::HoldForConsumers( |
| int buffer_id, |
| int num_clients) { |
| base::AutoLock lock(lock_); |
| - DCHECK(buffer_id >= 0); |
| - DCHECK(buffer_id < count()); |
| - DCHECK(IsAllocated()); |
| - Buffer* buffer = buffers_[buffer_id]; |
| + Buffer* buffer = GetBuffer(buffer_id); |
| + if (!buffer) { |
| + NOTREACHED() << "Invalid buffer_id."; |
| + return; |
| + } |
| DCHECK(buffer->held_by_producer); |
| DCHECK(!buffer->consumer_hold_count); |
| buffer->consumer_hold_count = num_clients; |
| // Note: |held_by_producer| will stay true until |
| // RelinquishProducerReservation() (usually called by destructor of the object |
| - // wrapping this buffer, e.g. a media::VideoFrame |
| + // wrapping this buffer, e.g. a media::VideoFrame). |
| } |
| void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id, |
| int num_clients) { |
| base::AutoLock lock(lock_); |
| - DCHECK(buffer_id >= 0); |
| - DCHECK(buffer_id < count()); |
| - DCHECK_GT(num_clients, 0); |
| - DCHECK(IsAllocated()); |
| - Buffer* buffer = buffers_[buffer_id]; |
| + Buffer* buffer = GetBuffer(buffer_id); |
| + if (!buffer) { |
| + NOTREACHED() << "Invalid buffer_id."; |
| + return; |
| + } |
| DCHECK_GE(buffer->consumer_hold_count, num_clients); |
| buffer->consumer_hold_count -= num_clients; |
| } |
| -// State query functions. |
| -size_t VideoCaptureBufferPool::GetMemorySize() const { |
| - // No need to take |lock_| currently. |
| - return size_; |
| -} |
| - |
| int VideoCaptureBufferPool::RecognizeReservedBuffer( |
| base::SharedMemoryHandle maybe_belongs_to_pool) { |
| base::AutoLock lock(lock_); |
| - for (int buffer_id = 0; buffer_id < count(); ++buffer_id) { |
| - Buffer* buffer = buffers_[buffer_id]; |
| - if (buffer->shared_memory.handle() == maybe_belongs_to_pool) { |
| - DCHECK(buffer->held_by_producer); |
| - return buffer_id; |
| + for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); it++) { |
| + if (it->second->shared_memory.handle() == maybe_belongs_to_pool) { |
| + DCHECK(it->second->held_by_producer); |
| + return it->first; |
| } |
| } |
| - return -1; // Buffer is not from our pool. |
| + return kInvalidId; // Buffer is not from our pool. |
| } |
| scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveI420VideoFrame( |
| const gfx::Size& size, |
| - int rotation) { |
| - if (GetMemorySize() != |
| - media::VideoFrame::AllocationSize(media::VideoFrame::I420, size)) { |
| - DCHECK_EQ(GetMemorySize(), |
| - media::VideoFrame::AllocationSize(media::VideoFrame::I420, size)); |
| - return NULL; |
| - } |
| - |
| + int rotation, |
| + int* buffer_id_to_drop) { |
| base::AutoLock lock(lock_); |
| - int buffer_id = ReserveForProducerInternal(); |
| - if (buffer_id < 0) |
| + 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( |
| @@ -146,7 +117,7 @@ scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveI420VideoFrame( |
| this, |
| buffer_id); |
| - Buffer* buffer = buffers_[buffer_id]; |
| + Buffer* buffer = GetBuffer(buffer_id); |
| // Wrap the buffer in a VideoFrame container. |
| scoped_refptr<media::VideoFrame> frame = |
| media::VideoFrame::WrapExternalSharedMemory( |
| @@ -155,13 +126,13 @@ scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveI420VideoFrame( |
| gfx::Rect(size), |
| size, |
| static_cast<uint8*>(buffer->shared_memory.memory()), |
| - GetMemorySize(), |
| + frame_bytes, |
| buffer->shared_memory.handle(), |
| base::TimeDelta(), |
| disposal_handler); |
| if (buffer->rotation != rotation) { |
| - // TODO(nick): Generalize the |rotation| mechanism. |
| + // TODO(jiayl): Generalize the |rotation| mechanism. |
| media::FillYUV(frame.get(), 0, 128, 128); |
| buffer->rotation = rotation; |
| } |
| @@ -169,45 +140,57 @@ scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveI420VideoFrame( |
| return frame; |
| } |
| -bool VideoCaptureBufferPool::IsAnyBufferHeldForConsumers() { |
| - base::AutoLock lock(lock_); |
| - for (int buffer_id = 0; buffer_id < count(); ++buffer_id) { |
| - Buffer* buffer = buffers_[buffer_id]; |
| - if (buffer->consumer_hold_count > 0) |
| - return true; |
| - } |
| - return false; |
| -} |
| - |
| VideoCaptureBufferPool::Buffer::Buffer() |
| : rotation(0), |
| held_by_producer(false), |
| consumer_hold_count(0) {} |
| -int VideoCaptureBufferPool::ReserveForProducerInternal() { |
| +int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size, |
| + int* buffer_id_to_drop) { |
| lock_.AssertAcquired(); |
| - DCHECK(IsAllocated()); |
| - |
| - int buffer_id = -1; |
| - for (int candidate_id = 0; candidate_id < count(); ++candidate_id) { |
| - Buffer* candidate = buffers_[candidate_id]; |
| - if (!candidate->consumer_hold_count && !candidate->held_by_producer) { |
| - buffer_id = candidate_id; |
| - break; |
| + |
| + // Look for a buffer that's allocated but not in use. We'll reuse any buffer |
| + // that's big enough. |
| + *buffer_id_to_drop = kInvalidId; |
| + for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); it++) { |
| + Buffer* buffer = it->second; |
| + if (!buffer->consumer_hold_count && !buffer->held_by_producer) { |
| + if (buffer->shared_memory.requested_size() >= size) { |
| + // Existing buffer is big enough. Reuse it. |
| + buffer->held_by_producer = true; |
| + return it->first; |
| + } else { |
| + // Existing buffer is too small. Free it so we can allocate a new one |
| + // after the loop. |
|
jiayl
2013/10/03 00:51:14
What if there is another free buffer that's big en
ncarter (slow)
2013/10/16 02:08:40
Done.
|
| + *buffer_id_to_drop = it->first; |
| + buffers_.erase(it); |
| + delete buffer; |
| + break; |
| + } |
| } |
| } |
| - if (buffer_id == -1) |
| - return -1; |
| - Buffer* buffer = buffers_[buffer_id]; |
| - CHECK_GE(buffer->shared_memory.requested_size(), size_); |
| - buffer->held_by_producer = true; |
| - return buffer_id; |
| + if (static_cast<int>(buffers_.size()) < count_) { |
| + // Grow the pool by creating a new buffer. |
| + int buffer_id = next_buffer_id_++; |
| + Buffer* buffer = new Buffer(); |
| + if (!buffer->shared_memory.CreateAndMapAnonymous(size)) |
| + return kInvalidId; |
| + buffer->held_by_producer = true; |
| + buffers_[buffer_id] = buffer; |
| + return buffer_id; |
| + } |
| + |
| + // The pool is at its size limit, and all buffers are in use. |
| + return kInvalidId; |
| } |
| -bool VideoCaptureBufferPool::IsAllocated() const { |
| - lock_.AssertAcquired(); |
| - return !buffers_.empty(); |
| +VideoCaptureBufferPool::Buffer* VideoCaptureBufferPool::GetBuffer( |
| + int buffer_id) { |
| + BufferMap::iterator it = buffers_.find(buffer_id); |
| + if (it == buffers_.end()) |
| + return NULL; |
| + return it->second; |
| } |
| } // namespace content |