[Session restore] Rename group name Enabled to Restore.
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_buffer_pool.cc
blobf583a94adaa638396431ecda7017aa787d99aaa2
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/stl_util.h"
12 #include "media/base/video_frame.h"
13 #include "media/base/video_util.h"
15 namespace content {
17 const int VideoCaptureBufferPool::kInvalidId = -1;
19 VideoCaptureBufferPool::VideoCaptureBufferPool(int count)
20 : count_(count),
21 next_buffer_id_(0) {
22 DCHECK_GT(count, 0);
25 VideoCaptureBufferPool::~VideoCaptureBufferPool() {
26 STLDeleteValues(&buffers_);
29 base::SharedMemoryHandle VideoCaptureBufferPool::ShareToProcess(
30 int buffer_id,
31 base::ProcessHandle process_handle,
32 size_t* memory_size) {
33 base::AutoLock lock(lock_);
35 Buffer* buffer = GetBuffer(buffer_id);
36 if (!buffer) {
37 NOTREACHED() << "Invalid buffer_id.";
38 return base::SharedMemory::NULLHandle();
40 base::SharedMemoryHandle remote_handle;
41 buffer->shared_memory.ShareToProcess(process_handle, &remote_handle);
42 *memory_size = buffer->shared_memory.requested_size();
43 return remote_handle;
46 bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id,
47 void** memory,
48 size_t* size) {
49 base::AutoLock lock(lock_);
51 Buffer* buffer = GetBuffer(buffer_id);
52 if (!buffer) {
53 NOTREACHED() << "Invalid buffer_id.";
54 return false;
57 DCHECK(buffer->held_by_producer);
58 *memory = buffer->shared_memory.memory();
59 *size = buffer->shared_memory.mapped_size();
60 return true;
63 int VideoCaptureBufferPool::ReserveForProducer(size_t size,
64 int* buffer_id_to_drop) {
65 base::AutoLock lock(lock_);
66 return ReserveForProducerInternal(size, buffer_id_to_drop);
69 void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) {
70 base::AutoLock lock(lock_);
71 Buffer* buffer = GetBuffer(buffer_id);
72 if (!buffer) {
73 NOTREACHED() << "Invalid buffer_id.";
74 return;
76 DCHECK(buffer->held_by_producer);
77 buffer->held_by_producer = false;
80 void VideoCaptureBufferPool::HoldForConsumers(
81 int buffer_id,
82 int num_clients) {
83 base::AutoLock lock(lock_);
84 Buffer* buffer = GetBuffer(buffer_id);
85 if (!buffer) {
86 NOTREACHED() << "Invalid buffer_id.";
87 return;
89 DCHECK(buffer->held_by_producer);
90 DCHECK(!buffer->consumer_hold_count);
92 buffer->consumer_hold_count = num_clients;
93 // Note: |held_by_producer| will stay true until
94 // RelinquishProducerReservation() (usually called by destructor of the object
95 // wrapping this buffer, e.g. a media::VideoFrame).
98 void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id,
99 int num_clients) {
100 base::AutoLock lock(lock_);
101 Buffer* buffer = GetBuffer(buffer_id);
102 if (!buffer) {
103 NOTREACHED() << "Invalid buffer_id.";
104 return;
106 DCHECK_GE(buffer->consumer_hold_count, num_clients);
108 buffer->consumer_hold_count -= num_clients;
111 VideoCaptureBufferPool::Buffer::Buffer()
112 : held_by_producer(false), consumer_hold_count(0) {}
114 int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size,
115 int* buffer_id_to_drop) {
116 lock_.AssertAcquired();
118 // Look for a buffer that's allocated, big enough, and not in use. Track the
119 // largest one that's not big enough, in case we have to reallocate a buffer.
120 *buffer_id_to_drop = kInvalidId;
121 size_t realloc_size = 0;
122 BufferMap::iterator realloc = buffers_.end();
123 for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); ++it) {
124 Buffer* buffer = it->second;
125 if (!buffer->consumer_hold_count && !buffer->held_by_producer) {
126 if (buffer->shared_memory.requested_size() >= size) {
127 // Existing buffer is big enough. Reuse it.
128 buffer->held_by_producer = true;
129 return it->first;
131 if (buffer->shared_memory.requested_size() > realloc_size) {
132 realloc_size = buffer->shared_memory.requested_size();
133 realloc = it;
138 // Preferentially grow the pool by creating a new buffer. If we're at maximum
139 // size, then reallocate by deleting an existing one instead.
140 if (buffers_.size() == static_cast<size_t>(count_)) {
141 if (realloc == buffers_.end()) {
142 // We're out of space, and can't find an unused buffer to reallocate.
143 return kInvalidId;
145 *buffer_id_to_drop = realloc->first;
146 delete realloc->second;
147 buffers_.erase(realloc);
150 // Create the new buffer.
151 int buffer_id = next_buffer_id_++;
152 scoped_ptr<Buffer> buffer(new Buffer());
153 if (size) {
154 // |size| can be 0 for buffers that do not require memory backing.
155 if (!buffer->shared_memory.CreateAndMapAnonymous(size))
156 return kInvalidId;
158 buffer->held_by_producer = true;
159 buffers_[buffer_id] = buffer.release();
160 return buffer_id;
163 VideoCaptureBufferPool::Buffer* VideoCaptureBufferPool::GetBuffer(
164 int buffer_id) {
165 BufferMap::iterator it = buffers_.find(buffer_id);
166 if (it == buffers_.end())
167 return NULL;
168 return it->second;
171 } // namespace content