Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(332)

Side by Side Diff: content/browser/renderer_host/media/video_capture_buffer_pool.cc

Issue 1064703002: VideoCaptureBufferPool: Refactor to allow support of non-ShMem backed buffers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "media/base/video_frame.h" 12 #include "media/base/video_frame.h"
13 #include "media/base/video_util.h" 13
14 using media::VideoFrame;
14 15
15 namespace content { 16 namespace content {
16 17
17 const int VideoCaptureBufferPool::kInvalidId = -1; 18 const int VideoCaptureBufferPool::kInvalidId = -1;
18 19
20 // Tracker specifics for SharedMemory.
21 class VideoCaptureBufferPool::SharedMemTracker final : public Tracker {
22 public:
23 SharedMemTracker();
24
25 bool Init(const gfx::Size& dimensions) override;
26 void* storage() override { return shared_memory_.memory(); }
27 size_t requested_size() override { return shared_memory_.requested_size(); }
28 size_t mapped_size() override { return shared_memory_.mapped_size(); }
29
30 bool ShareToProcess(base::ProcessHandle process_handle,
31 base::SharedMemoryHandle* new_handle) override {
32 return shared_memory_.ShareToProcess(process_handle, new_handle);
33 }
34
35 private:
36 // The memory created to be shared with renderer processes.
37 base::SharedMemory shared_memory_;
38 };
39
40 VideoCaptureBufferPool::SharedMemTracker::SharedMemTracker()
41 : Tracker() {}
42
43 bool VideoCaptureBufferPool::SharedMemTracker::Init(
44 const gfx::Size& dimensions) {
45 // Input |dimensions| can be 0 for buffers that do not require memory backing.
46 // The allocated size is calculated using VideoFrame methods since this will
47 // be the abstraction used to wrap the underlying data.
48 return shared_memory_.CreateAndMapAnonymous(
49 VideoFrame::AllocationSize(VideoFrame::I420, dimensions));
50 }
51
52 //static
53 scoped_ptr<VideoCaptureBufferPool::Tracker>
54 VideoCaptureBufferPool::Tracker::CreateTracker() {
55 return make_scoped_ptr(new SharedMemTracker());
56 }
57
58 VideoCaptureBufferPool::Tracker::~Tracker() {}
59
19 VideoCaptureBufferPool::VideoCaptureBufferPool(int count) 60 VideoCaptureBufferPool::VideoCaptureBufferPool(int count)
20 : count_(count), 61 : count_(count),
21 next_buffer_id_(0) { 62 next_buffer_id_(0) {
22 DCHECK_GT(count, 0); 63 DCHECK_GT(count, 0);
23 } 64 }
24 65
25 VideoCaptureBufferPool::~VideoCaptureBufferPool() { 66 VideoCaptureBufferPool::~VideoCaptureBufferPool() {
26 STLDeleteValues(&buffers_); 67 STLDeleteValues(&buffers_);
27 } 68 }
28 69
29 base::SharedMemoryHandle VideoCaptureBufferPool::ShareToProcess( 70 base::SharedMemoryHandle VideoCaptureBufferPool::ShareToProcess(
30 int buffer_id, 71 int buffer_id,
31 base::ProcessHandle process_handle, 72 base::ProcessHandle process_handle,
32 size_t* memory_size) { 73 size_t* memory_size) {
33 base::AutoLock lock(lock_); 74 base::AutoLock lock(lock_);
34 75
35 Buffer* buffer = GetBuffer(buffer_id); 76 Tracker* buffer = GetBuffer(buffer_id);
36 if (!buffer) { 77 if (!buffer) {
37 NOTREACHED() << "Invalid buffer_id."; 78 NOTREACHED() << "Invalid buffer_id.";
38 return base::SharedMemory::NULLHandle(); 79 return base::SharedMemory::NULLHandle();
39 } 80 }
40 base::SharedMemoryHandle remote_handle; 81 base::SharedMemoryHandle remote_handle;
41 buffer->shared_memory.ShareToProcess(process_handle, &remote_handle); 82 if (buffer->ShareToProcess(process_handle, &remote_handle)) {
42 *memory_size = buffer->shared_memory.requested_size(); 83 *memory_size = buffer->mapped_size();
43 return remote_handle; 84 return remote_handle;
85 }
86 DPLOG(ERROR) << "Error mapping Shared Memory.";
87 return base::SharedMemoryHandle();
44 } 88 }
45 89
46 bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id, 90 bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id,
47 void** memory, 91 void** storage,
48 size_t* size) { 92 size_t* size) {
49 base::AutoLock lock(lock_); 93 base::AutoLock lock(lock_);
50 94
51 Buffer* buffer = GetBuffer(buffer_id); 95 Tracker* buffer = GetBuffer(buffer_id);
52 if (!buffer) { 96 if (!buffer) {
53 NOTREACHED() << "Invalid buffer_id."; 97 NOTREACHED() << "Invalid buffer_id.";
54 return false; 98 return false;
55 } 99 }
56 100
57 DCHECK(buffer->held_by_producer); 101 DCHECK(buffer->held_by_producer());
58 *memory = buffer->shared_memory.memory(); 102 *storage = buffer->storage();
59 *size = buffer->shared_memory.mapped_size(); 103 *size = buffer->mapped_size();
60 return true; 104 return true;
61 } 105 }
62 106
63 int VideoCaptureBufferPool::ReserveForProducer(size_t size, 107 int VideoCaptureBufferPool::ReserveForProducer(
64 int* buffer_id_to_drop) { 108 const media::VideoCaptureFormat& format,
109 int* buffer_id_to_drop) {
65 base::AutoLock lock(lock_); 110 base::AutoLock lock(lock_);
66 return ReserveForProducerInternal(size, buffer_id_to_drop); 111 return ReserveForProducerInternal(format, buffer_id_to_drop);
67 } 112 }
68 113
69 void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) { 114 void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) {
70 base::AutoLock lock(lock_); 115 base::AutoLock lock(lock_);
71 Buffer* buffer = GetBuffer(buffer_id); 116 Tracker* buffer = GetBuffer(buffer_id);
72 if (!buffer) { 117 if (!buffer) {
73 NOTREACHED() << "Invalid buffer_id."; 118 NOTREACHED() << "Invalid buffer_id.";
74 return; 119 return;
75 } 120 }
76 DCHECK(buffer->held_by_producer); 121 DCHECK(buffer->held_by_producer());
77 buffer->held_by_producer = false; 122 buffer->set_held_by_producer(false);
78 } 123 }
79 124
80 void VideoCaptureBufferPool::HoldForConsumers( 125 void VideoCaptureBufferPool::HoldForConsumers(
81 int buffer_id, 126 int buffer_id,
82 int num_clients) { 127 int num_clients) {
83 base::AutoLock lock(lock_); 128 base::AutoLock lock(lock_);
84 Buffer* buffer = GetBuffer(buffer_id); 129 Tracker* buffer = GetBuffer(buffer_id);
85 if (!buffer) { 130 if (!buffer) {
86 NOTREACHED() << "Invalid buffer_id."; 131 NOTREACHED() << "Invalid buffer_id.";
87 return; 132 return;
88 } 133 }
89 DCHECK(buffer->held_by_producer); 134 DCHECK(buffer->held_by_producer());
90 DCHECK(!buffer->consumer_hold_count); 135 DCHECK(!buffer->consumer_hold_count());
91 136
92 buffer->consumer_hold_count = num_clients; 137 buffer->set_consumer_hold_count(num_clients);
93 // Note: |held_by_producer| will stay true until 138 // Note: |held_by_producer()| will stay true until
94 // RelinquishProducerReservation() (usually called by destructor of the object 139 // RelinquishProducerReservation() (usually called by destructor of the object
95 // wrapping this buffer, e.g. a media::VideoFrame). 140 // wrapping this buffer, e.g. a media::VideoFrame).
96 } 141 }
97 142
98 void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id, 143 void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id,
99 int num_clients) { 144 int num_clients) {
100 base::AutoLock lock(lock_); 145 base::AutoLock lock(lock_);
101 Buffer* buffer = GetBuffer(buffer_id); 146 Tracker* buffer = GetBuffer(buffer_id);
102 if (!buffer) { 147 if (!buffer) {
103 NOTREACHED() << "Invalid buffer_id."; 148 NOTREACHED() << "Invalid buffer_id.";
104 return; 149 return;
105 } 150 }
106 DCHECK_GE(buffer->consumer_hold_count, num_clients); 151 DCHECK_GE(buffer->consumer_hold_count(), num_clients);
107 152
108 buffer->consumer_hold_count -= num_clients; 153 buffer->set_consumer_hold_count(buffer->consumer_hold_count() - num_clients);
109 } 154 }
110 155
111 VideoCaptureBufferPool::Buffer::Buffer() 156 int VideoCaptureBufferPool::ReserveForProducerInternal(
112 : held_by_producer(false), consumer_hold_count(0) {} 157 const media::VideoCaptureFormat& format,
113 158 int* buffer_id_to_drop) {
114 int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size,
115 int* buffer_id_to_drop) {
116 lock_.AssertAcquired(); 159 lock_.AssertAcquired();
117 160
161 const size_t size_in_bytes =
162 VideoFrame::AllocationSize(VideoFrame::I420, format.frame_size);
miu 2015/04/08 01:20:00 The call to AllocationSize() should use the format
mcasas 2015/04/08 22:07:05 Done.
118 // Look for a buffer that's allocated, big enough, and not in use. Track the 163 // 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. 164 // largest one that's not big enough, in case we have to reallocate a buffer.
120 *buffer_id_to_drop = kInvalidId; 165 *buffer_id_to_drop = kInvalidId;
121 size_t realloc_size = 0; 166 size_t realloc_size = 0;
122 BufferMap::iterator realloc = buffers_.end(); 167 BufferMap::iterator buffer_to_drop = buffers_.end();
123 for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); ++it) { 168 for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); ++it) {
124 Buffer* buffer = it->second; 169 Tracker* const buffer = it->second;
125 if (!buffer->consumer_hold_count && !buffer->held_by_producer) { 170 if (!buffer->consumer_hold_count() && !buffer->held_by_producer()) {
126 if (buffer->shared_memory.requested_size() >= size) { 171 if (buffer->requested_size() >= size_in_bytes) {
127 // Existing buffer is big enough. Reuse it. 172 // Existing buffer is big enough. Reuse it.
128 buffer->held_by_producer = true; 173 buffer->set_held_by_producer(true);
129 return it->first; 174 return it->first;
130 } 175 }
131 if (buffer->shared_memory.requested_size() > realloc_size) { 176 if (buffer->requested_size() > realloc_size) {
132 realloc_size = buffer->shared_memory.requested_size(); 177 realloc_size = buffer->requested_size();
133 realloc = it; 178 buffer_to_drop = it;
134 } 179 }
135 } 180 }
136 } 181 }
137 182
138 // Preferentially grow the pool by creating a new buffer. If we're at maximum 183 // Preferably grow the pool by creating a new buffer. If we're at maximum
139 // size, then reallocate by deleting an existing one instead. 184 // size, then reallocate by deleting an existing one instead.
140 if (buffers_.size() == static_cast<size_t>(count_)) { 185 if (buffers_.size() == static_cast<size_t>(count_)) {
141 if (realloc == buffers_.end()) { 186 if (buffer_to_drop == buffers_.end()) {
142 // We're out of space, and can't find an unused buffer to reallocate. 187 // We're out of space, and can't find an unused buffer to reallocate.
143 return kInvalidId; 188 return kInvalidId;
144 } 189 }
145 *buffer_id_to_drop = realloc->first; 190 *buffer_id_to_drop = buffer_to_drop->first;
146 delete realloc->second; 191 delete buffer_to_drop->second;
147 buffers_.erase(realloc); 192 buffers_.erase(buffer_to_drop);
148 } 193 }
149 194
150 // Create the new buffer. 195 // Create the new buffer.
151 int buffer_id = next_buffer_id_++; 196 const int buffer_id = next_buffer_id_++;
152 scoped_ptr<Buffer> buffer(new Buffer()); 197 scoped_ptr<Tracker> tracker = Tracker::CreateTracker();
153 if (size) { 198 if (!tracker->Init(format.frame_size))
154 // |size| can be 0 for buffers that do not require memory backing. 199 return kInvalidId;
155 if (!buffer->shared_memory.CreateAndMapAnonymous(size)) 200 tracker->set_held_by_producer(true);
156 return kInvalidId; 201 buffers_[buffer_id] = tracker.release();
157 } 202
158 buffer->held_by_producer = true;
159 buffers_[buffer_id] = buffer.release();
160 return buffer_id; 203 return buffer_id;
161 } 204 }
162 205
163 VideoCaptureBufferPool::Buffer* VideoCaptureBufferPool::GetBuffer( 206 VideoCaptureBufferPool::Tracker* VideoCaptureBufferPool::GetBuffer(
164 int buffer_id) { 207 int buffer_id) {
165 BufferMap::iterator it = buffers_.find(buffer_id); 208 BufferMap::const_iterator it = buffers_.find(buffer_id);
166 if (it == buffers_.end()) 209 return (it == buffers_.end()) ? NULL : it->second;
167 return NULL;
168 return it->second;
169 } 210 }
170 211
171 } // namespace content 212 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698