OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" | 5 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 24 matching lines...) Expand all Loading... | |
35 if (!buffer) { | 35 if (!buffer) { |
36 NOTREACHED() << "Invalid buffer_id."; | 36 NOTREACHED() << "Invalid buffer_id."; |
37 return base::SharedMemory::NULLHandle(); | 37 return base::SharedMemory::NULLHandle(); |
38 } | 38 } |
39 base::SharedMemoryHandle remote_handle; | 39 base::SharedMemoryHandle remote_handle; |
40 buffer->shared_memory.ShareToProcess(process_handle, &remote_handle); | 40 buffer->shared_memory.ShareToProcess(process_handle, &remote_handle); |
41 *memory_size = buffer->shared_memory.requested_size(); | 41 *memory_size = buffer->shared_memory.requested_size(); |
42 return remote_handle; | 42 return remote_handle; |
43 } | 43 } |
44 | 44 |
45 bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id, | |
46 void** memory, | |
47 size_t* size) { | |
48 base::AutoLock lock(lock_); | |
49 | |
50 Buffer* buffer = GetBuffer(buffer_id); | |
51 if (!buffer) { | |
52 NOTREACHED() << "Invalid buffer_id."; | |
53 return false; | |
54 } | |
55 | |
56 DCHECK(buffer->held_by_producer); | |
57 *memory = buffer->shared_memory.memory(); | |
58 *size = buffer->shared_memory.mapped_size(); | |
59 return true; | |
60 } | |
61 | |
45 int VideoCaptureBufferPool::ReserveForProducer(size_t size, | 62 int VideoCaptureBufferPool::ReserveForProducer(size_t size, |
46 int* buffer_id_to_drop) { | 63 int* buffer_id_to_drop) { |
47 base::AutoLock lock(lock_); | 64 base::AutoLock lock(lock_); |
48 return ReserveForProducerInternal(size, buffer_id_to_drop); | 65 return ReserveForProducerInternal(size, buffer_id_to_drop); |
49 } | 66 } |
50 | 67 |
51 void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) { | 68 void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) { |
52 base::AutoLock lock(lock_); | 69 base::AutoLock lock(lock_); |
53 Buffer* buffer = GetBuffer(buffer_id); | 70 Buffer* buffer = GetBuffer(buffer_id); |
54 if (!buffer) { | 71 if (!buffer) { |
(...skipping 28 matching lines...) Expand all Loading... | |
83 Buffer* buffer = GetBuffer(buffer_id); | 100 Buffer* buffer = GetBuffer(buffer_id); |
84 if (!buffer) { | 101 if (!buffer) { |
85 NOTREACHED() << "Invalid buffer_id."; | 102 NOTREACHED() << "Invalid buffer_id."; |
86 return; | 103 return; |
87 } | 104 } |
88 DCHECK_GE(buffer->consumer_hold_count, num_clients); | 105 DCHECK_GE(buffer->consumer_hold_count, num_clients); |
89 | 106 |
90 buffer->consumer_hold_count -= num_clients; | 107 buffer->consumer_hold_count -= num_clients; |
91 } | 108 } |
92 | 109 |
93 int VideoCaptureBufferPool::RecognizeReservedBuffer( | |
94 base::SharedMemoryHandle maybe_belongs_to_pool) { | |
95 base::AutoLock lock(lock_); | |
96 for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); it++) { | |
97 if (it->second->shared_memory.handle() == maybe_belongs_to_pool) { | |
98 DCHECK(it->second->held_by_producer); | |
99 return it->first; | |
100 } | |
101 } | |
102 return kInvalidId; // Buffer is not from our pool. | |
103 } | |
104 | |
105 scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveI420VideoFrame( | |
106 const gfx::Size& size, | |
107 int rotation, | |
108 int* buffer_id_to_drop) { | |
109 base::AutoLock lock(lock_); | |
110 | |
111 size_t frame_bytes = | |
112 media::VideoFrame::AllocationSize(media::VideoFrame::I420, size); | |
113 | |
114 int buffer_id = ReserveForProducerInternal(frame_bytes, buffer_id_to_drop); | |
115 if (buffer_id == kInvalidId) | |
116 return NULL; | |
117 | |
118 base::Closure disposal_handler = base::Bind( | |
119 &VideoCaptureBufferPool::RelinquishProducerReservation, | |
120 this, | |
121 buffer_id); | |
122 | |
123 Buffer* buffer = GetBuffer(buffer_id); | |
124 // Wrap the buffer in a VideoFrame container. | |
125 scoped_refptr<media::VideoFrame> frame = | |
126 media::VideoFrame::WrapExternalSharedMemory( | |
127 media::VideoFrame::I420, | |
128 size, | |
129 gfx::Rect(size), | |
130 size, | |
131 static_cast<uint8*>(buffer->shared_memory.memory()), | |
132 frame_bytes, | |
133 buffer->shared_memory.handle(), | |
134 base::TimeDelta(), | |
135 disposal_handler); | |
136 | |
137 if (buffer->rotation != rotation) { | |
138 // TODO(jiayl): Generalize the |rotation| mechanism. | |
139 media::FillYUV(frame.get(), 0, 128, 128); | |
140 buffer->rotation = rotation; | |
141 } | |
142 | |
143 return frame; | |
144 } | |
145 | |
146 VideoCaptureBufferPool::Buffer::Buffer() | 110 VideoCaptureBufferPool::Buffer::Buffer() |
147 : rotation(0), | 111 : held_by_producer(false), consumer_hold_count(0) {} |
148 held_by_producer(false), | |
149 consumer_hold_count(0) {} | |
150 | 112 |
151 int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size, | 113 int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size, |
152 int* buffer_id_to_drop) { | 114 int* buffer_id_to_drop) { |
153 lock_.AssertAcquired(); | 115 lock_.AssertAcquired(); |
154 | 116 |
155 // Look for a buffer that's allocated, big enough, and not in use. | 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. | |
156 *buffer_id_to_drop = kInvalidId; | 119 *buffer_id_to_drop = kInvalidId; |
120 size_t realloc_size = 0; | |
121 BufferMap::iterator realloc = buffers_.end(); | |
157 for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); it++) { | 122 for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); it++) { |
wjia(left Chromium)
2013/11/19 01:47:35
nit: ++it
sheu
2013/11/19 20:28:17
Done.
| |
158 Buffer* buffer = it->second; | 123 Buffer* buffer = it->second; |
159 if (!buffer->consumer_hold_count && !buffer->held_by_producer) { | 124 if (!buffer->consumer_hold_count && !buffer->held_by_producer) { |
160 if (buffer->shared_memory.requested_size() >= size) { | 125 if (buffer->shared_memory.requested_size() >= size) { |
161 // Existing buffer is big enough. Reuse it. | 126 // Existing buffer is big enough. Reuse it. |
162 buffer->held_by_producer = true; | 127 buffer->held_by_producer = true; |
163 return it->first; | 128 return it->first; |
164 } | 129 } |
130 if (buffer->shared_memory.requested_size() > realloc_size) { | |
131 realloc_size = buffer->shared_memory.requested_size(); | |
132 realloc = it; | |
wjia(left Chromium)
2013/11/19 01:47:35
OOC, what's the reason to reallocate the largest o
sheu
2013/11/19 20:28:17
VideoCaptureBufferPool doesn't downsize until it h
| |
133 } | |
165 } | 134 } |
166 } | 135 } |
167 | 136 |
168 // Look for a buffer that's not in use, that we can reallocate. | 137 // Preferentially grow the pool by creating a new buffer. If we're at maximum |
169 for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); it++) { | 138 // size, then reallocate by deleting an existing one instead. |
170 Buffer* buffer = it->second; | 139 if (buffers_.size() == static_cast<size_t>(count_)) { |
171 if (!buffer->consumer_hold_count && !buffer->held_by_producer) { | 140 if (realloc == buffers_.end()) { |
172 // Existing buffer is too small. Free it so we can allocate a new one | 141 // We're out of space, and can't find an unused buffer to reallocate. |
173 // after the loop. | 142 return kInvalidId; |
174 *buffer_id_to_drop = it->first; | |
175 buffers_.erase(it); | |
176 delete buffer; | |
177 break; | |
178 } | 143 } |
144 *buffer_id_to_drop = realloc->first; | |
145 delete realloc->second; | |
146 buffers_.erase(realloc); | |
179 } | 147 } |
180 | 148 |
181 // If possible, grow the pool by creating a new buffer. | 149 // Create the new buffer. |
182 if (static_cast<int>(buffers_.size()) < count_) { | 150 int buffer_id = next_buffer_id_++; |
183 int buffer_id = next_buffer_id_++; | 151 scoped_ptr<Buffer> buffer(new Buffer()); |
184 scoped_ptr<Buffer> buffer(new Buffer()); | 152 if (size) { |
153 // |size| can be 0 for buffers that do not require memory backing. | |
185 if (!buffer->shared_memory.CreateAndMapAnonymous(size)) | 154 if (!buffer->shared_memory.CreateAndMapAnonymous(size)) |
186 return kInvalidId; | 155 return kInvalidId; |
187 buffer->held_by_producer = true; | |
188 buffers_[buffer_id] = buffer.release(); | |
189 return buffer_id; | |
190 } | 156 } |
191 | 157 buffer->held_by_producer = true; |
192 // The pool is at its size limit, and all buffers are in use. | 158 buffers_[buffer_id] = buffer.release(); |
193 return kInvalidId; | 159 return buffer_id; |
194 } | 160 } |
195 | 161 |
196 VideoCaptureBufferPool::Buffer* VideoCaptureBufferPool::GetBuffer( | 162 VideoCaptureBufferPool::Buffer* VideoCaptureBufferPool::GetBuffer( |
197 int buffer_id) { | 163 int buffer_id) { |
198 BufferMap::iterator it = buffers_.find(buffer_id); | 164 BufferMap::iterator it = buffers_.find(buffer_id); |
199 if (it == buffers_.end()) | 165 if (it == buffers_.end()) |
200 return NULL; | 166 return NULL; |
201 return it->second; | 167 return it->second; |
202 } | 168 } |
203 | 169 |
204 } // namespace content | 170 } // namespace content |
205 | 171 |
OLD | NEW |