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"
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"
17 const int VideoCaptureBufferPool::kInvalidId
= -1;
19 VideoCaptureBufferPool::VideoCaptureBufferPool(int count
)
24 VideoCaptureBufferPool::~VideoCaptureBufferPool() {
25 STLDeleteValues(&buffers_
);
28 base::SharedMemoryHandle
VideoCaptureBufferPool::ShareToProcess(
30 base::ProcessHandle process_handle
,
31 size_t* memory_size
) {
32 base::AutoLock
lock(lock_
);
34 Buffer
* buffer
= GetBuffer(buffer_id
);
36 NOTREACHED() << "Invalid buffer_id.";
37 return base::SharedMemory::NULLHandle();
39 base::SharedMemoryHandle remote_handle
;
40 buffer
->shared_memory
.ShareToProcess(process_handle
, &remote_handle
);
41 *memory_size
= buffer
->shared_memory
.requested_size();
45 bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id
,
48 base::AutoLock
lock(lock_
);
50 Buffer
* buffer
= GetBuffer(buffer_id
);
52 NOTREACHED() << "Invalid buffer_id.";
56 DCHECK(buffer
->held_by_producer
);
57 *memory
= buffer
->shared_memory
.memory();
58 *size
= buffer
->shared_memory
.mapped_size();
62 int VideoCaptureBufferPool::ReserveForProducer(size_t size
,
63 int* buffer_id_to_drop
) {
64 base::AutoLock
lock(lock_
);
65 return ReserveForProducerInternal(size
, buffer_id_to_drop
);
68 void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id
) {
69 base::AutoLock
lock(lock_
);
70 Buffer
* buffer
= GetBuffer(buffer_id
);
72 NOTREACHED() << "Invalid buffer_id.";
75 DCHECK(buffer
->held_by_producer
);
76 buffer
->held_by_producer
= false;
79 void VideoCaptureBufferPool::HoldForConsumers(
82 base::AutoLock
lock(lock_
);
83 Buffer
* buffer
= GetBuffer(buffer_id
);
85 NOTREACHED() << "Invalid buffer_id.";
88 DCHECK(buffer
->held_by_producer
);
89 DCHECK(!buffer
->consumer_hold_count
);
91 buffer
->consumer_hold_count
= num_clients
;
92 // Note: |held_by_producer| will stay true until
93 // RelinquishProducerReservation() (usually called by destructor of the object
94 // wrapping this buffer, e.g. a media::VideoFrame).
97 void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id
,
99 base::AutoLock
lock(lock_
);
100 Buffer
* buffer
= GetBuffer(buffer_id
);
102 NOTREACHED() << "Invalid buffer_id.";
105 DCHECK_GE(buffer
->consumer_hold_count
, num_clients
);
107 buffer
->consumer_hold_count
-= num_clients
;
110 VideoCaptureBufferPool::Buffer::Buffer()
111 : held_by_producer(false), consumer_hold_count(0) {}
113 int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size
,
114 int* buffer_id_to_drop
) {
115 lock_
.AssertAcquired();
117 // Look for a buffer that's allocated, big enough, and not in use. Track the
118 // largest one that's not big enough, in case we have to reallocate a buffer.
119 *buffer_id_to_drop
= kInvalidId
;
120 size_t realloc_size
= 0;
121 BufferMap::iterator realloc
= buffers_
.end();
122 for (BufferMap::iterator it
= buffers_
.begin(); it
!= buffers_
.end(); ++it
) {
123 Buffer
* buffer
= it
->second
;
124 if (!buffer
->consumer_hold_count
&& !buffer
->held_by_producer
) {
125 if (buffer
->shared_memory
.requested_size() >= size
) {
126 // Existing buffer is big enough. Reuse it.
127 buffer
->held_by_producer
= true;
130 if (buffer
->shared_memory
.requested_size() > realloc_size
) {
131 realloc_size
= buffer
->shared_memory
.requested_size();
137 // Preferentially grow the pool by creating a new buffer. If we're at maximum
138 // size, then reallocate by deleting an existing one instead.
139 if (buffers_
.size() == static_cast<size_t>(count_
)) {
140 if (realloc
== buffers_
.end()) {
141 // We're out of space, and can't find an unused buffer to reallocate.
144 *buffer_id_to_drop
= realloc
->first
;
145 delete realloc
->second
;
146 buffers_
.erase(realloc
);
149 // Create the new buffer.
150 int buffer_id
= next_buffer_id_
++;
151 scoped_ptr
<Buffer
> buffer(new Buffer());
153 // |size| can be 0 for buffers that do not require memory backing.
154 if (!buffer
->shared_memory
.CreateAndMapAnonymous(size
))
157 buffer
->held_by_producer
= true;
158 buffers_
[buffer_id
] = buffer
.release();
162 VideoCaptureBufferPool::Buffer
* VideoCaptureBufferPool::GetBuffer(
164 BufferMap::iterator it
= buffers_
.find(buffer_id
);
165 if (it
== buffers_
.end())
170 } // namespace content