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

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

Issue 2361173002: Move classses VideoCaptureDeviceClient and VideoCaptureBufferPool to media/capture/video (Closed)
Patch Set: mcasas@ comments Created 4 years, 2 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
(Empty)
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.
4
5 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
6
7 #include <memory>
8
9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/stl_util.h"
12 #include "build/build_config.h"
13 #include "content/browser/renderer_host/media/video_capture_buffer_handle.h"
14 #include "content/browser/renderer_host/media/video_capture_buffer_tracker.h"
15 #include "content/browser/renderer_host/media/video_capture_buffer_tracker_facto ry.h"
16 #include "ui/gfx/buffer_format_util.h"
17
18 namespace content {
19
20 VideoCaptureBufferPoolImpl::VideoCaptureBufferPoolImpl(int count)
21 : count_(count),
22 next_buffer_id_(0),
23 last_relinquished_buffer_id_(kInvalidId) {
24 DCHECK_GT(count, 0);
25 }
26
27 VideoCaptureBufferPoolImpl::~VideoCaptureBufferPoolImpl() {
28 base::STLDeleteValues(&trackers_);
29 }
30
31 bool VideoCaptureBufferPoolImpl::ShareToProcess(
32 int buffer_id,
33 base::ProcessHandle process_handle,
34 base::SharedMemoryHandle* new_handle) {
35 base::AutoLock lock(lock_);
36
37 VideoCaptureBufferTracker* tracker = GetTracker(buffer_id);
38 if (!tracker) {
39 NOTREACHED() << "Invalid buffer_id.";
40 return false;
41 }
42 if (tracker->ShareToProcess(process_handle, new_handle))
43 return true;
44 DPLOG(ERROR) << "Error mapping memory";
45 return false;
46 }
47
48 bool VideoCaptureBufferPoolImpl::ShareToProcess2(
49 int buffer_id,
50 int plane,
51 base::ProcessHandle process_handle,
52 gfx::GpuMemoryBufferHandle* new_handle) {
53 base::AutoLock lock(lock_);
54
55 VideoCaptureBufferTracker* tracker = GetTracker(buffer_id);
56 if (!tracker) {
57 NOTREACHED() << "Invalid buffer_id.";
58 return false;
59 }
60 if (tracker->ShareToProcess2(plane, process_handle, new_handle))
61 return true;
62 DPLOG(ERROR) << "Error mapping memory";
63 return false;
64 }
65
66 std::unique_ptr<VideoCaptureBufferHandle>
67 VideoCaptureBufferPoolImpl::GetBufferHandle(int buffer_id) {
68 base::AutoLock lock(lock_);
69
70 VideoCaptureBufferTracker* tracker = GetTracker(buffer_id);
71 if (!tracker) {
72 NOTREACHED() << "Invalid buffer_id.";
73 return std::unique_ptr<VideoCaptureBufferHandle>();
74 }
75
76 DCHECK(tracker->held_by_producer());
77 return tracker->GetBufferHandle();
78 }
79
80 int VideoCaptureBufferPoolImpl::ReserveForProducer(
81 const gfx::Size& dimensions,
82 media::VideoPixelFormat format,
83 media::VideoPixelStorage storage,
84 int* buffer_id_to_drop) {
85 base::AutoLock lock(lock_);
86 return ReserveForProducerInternal(dimensions, format, storage,
87 buffer_id_to_drop);
88 }
89
90 void VideoCaptureBufferPoolImpl::RelinquishProducerReservation(int buffer_id) {
91 base::AutoLock lock(lock_);
92 VideoCaptureBufferTracker* tracker = GetTracker(buffer_id);
93 if (!tracker) {
94 NOTREACHED() << "Invalid buffer_id.";
95 return;
96 }
97 DCHECK(tracker->held_by_producer());
98 tracker->set_held_by_producer(false);
99 last_relinquished_buffer_id_ = buffer_id;
100 }
101
102 void VideoCaptureBufferPoolImpl::HoldForConsumers(int buffer_id,
103 int num_clients) {
104 base::AutoLock lock(lock_);
105 VideoCaptureBufferTracker* tracker = GetTracker(buffer_id);
106 if (!tracker) {
107 NOTREACHED() << "Invalid buffer_id.";
108 return;
109 }
110 DCHECK(tracker->held_by_producer());
111 DCHECK(!tracker->consumer_hold_count());
112
113 tracker->set_consumer_hold_count(num_clients);
114 // Note: |held_by_producer()| will stay true until
115 // RelinquishProducerReservation() (usually called by destructor of the object
116 // wrapping this tracker, e.g. a media::VideoFrame).
117 }
118
119 void VideoCaptureBufferPoolImpl::RelinquishConsumerHold(int buffer_id,
120 int num_clients) {
121 base::AutoLock lock(lock_);
122 VideoCaptureBufferTracker* tracker = GetTracker(buffer_id);
123 if (!tracker) {
124 NOTREACHED() << "Invalid buffer_id.";
125 return;
126 }
127 DCHECK_GE(tracker->consumer_hold_count(), num_clients);
128
129 tracker->set_consumer_hold_count(tracker->consumer_hold_count() -
130 num_clients);
131 }
132
133 int VideoCaptureBufferPoolImpl::ResurrectLastForProducer(
134 const gfx::Size& dimensions,
135 media::VideoPixelFormat format,
136 media::VideoPixelStorage storage) {
137 base::AutoLock lock(lock_);
138
139 // Return early if the last relinquished buffer has been re-used already.
140 if (last_relinquished_buffer_id_ == kInvalidId)
141 return kInvalidId;
142
143 // If there are no consumers reading from this buffer, then it's safe to
144 // provide this buffer back to the producer (because the producer may
145 // potentially modify the content). Check that the expected dimensions,
146 // format, and storage match.
147 TrackerMap::iterator it = trackers_.find(last_relinquished_buffer_id_);
148 DCHECK(it != trackers_.end());
149 DCHECK(!it->second->held_by_producer());
150 if (it->second->consumer_hold_count() == 0 &&
151 it->second->dimensions() == dimensions &&
152 it->second->pixel_format() == format &&
153 it->second->storage_type() == storage) {
154 it->second->set_held_by_producer(true);
155 const int resurrected_buffer_id = last_relinquished_buffer_id_;
156 last_relinquished_buffer_id_ = kInvalidId;
157 return resurrected_buffer_id;
158 }
159
160 return kInvalidId;
161 }
162
163 double VideoCaptureBufferPoolImpl::GetBufferPoolUtilization() const {
164 base::AutoLock lock(lock_);
165 int num_buffers_held = 0;
166 for (const auto& entry : trackers_) {
167 VideoCaptureBufferTracker* const tracker = entry.second;
168 if (tracker->held_by_producer() || tracker->consumer_hold_count() > 0)
169 ++num_buffers_held;
170 }
171 return static_cast<double>(num_buffers_held) / count_;
172 }
173
174 int VideoCaptureBufferPoolImpl::ReserveForProducerInternal(
175 const gfx::Size& dimensions,
176 media::VideoPixelFormat pixel_format,
177 media::VideoPixelStorage storage_type,
178 int* buffer_id_to_drop) {
179 lock_.AssertAcquired();
180
181 const size_t size_in_pixels = dimensions.GetArea();
182 // Look for a tracker that's allocated, big enough, and not in use. Track the
183 // largest one that's not big enough, in case we have to reallocate a tracker.
184 *buffer_id_to_drop = kInvalidId;
185 size_t largest_size_in_pixels = 0;
186 TrackerMap::iterator tracker_of_last_resort = trackers_.end();
187 TrackerMap::iterator tracker_to_drop = trackers_.end();
188 for (TrackerMap::iterator it = trackers_.begin(); it != trackers_.end();
189 ++it) {
190 VideoCaptureBufferTracker* const tracker = it->second;
191 if (!tracker->consumer_hold_count() && !tracker->held_by_producer()) {
192 if (tracker->max_pixel_count() >= size_in_pixels &&
193 (tracker->pixel_format() == pixel_format) &&
194 (tracker->storage_type() == storage_type)) {
195 if (it->first == last_relinquished_buffer_id_) {
196 // This buffer would do just fine, but avoid returning it because the
197 // client may want to resurrect it. It will be returned perforce if
198 // the pool has reached it's maximum limit (see code below).
199 tracker_of_last_resort = it;
200 continue;
201 }
202 // Existing tracker is big enough and has correct format. Reuse it.
203 tracker->set_dimensions(dimensions);
204 tracker->set_held_by_producer(true);
205 return it->first;
206 }
207 if (tracker->max_pixel_count() > largest_size_in_pixels) {
208 largest_size_in_pixels = tracker->max_pixel_count();
209 tracker_to_drop = it;
210 }
211 }
212 }
213
214 // Preferably grow the pool by creating a new tracker. If we're at maximum
215 // size, then try using |tracker_of_last_resort| or reallocate by deleting an
216 // existing one instead.
217 if (trackers_.size() == static_cast<size_t>(count_)) {
218 if (tracker_of_last_resort != trackers_.end()) {
219 last_relinquished_buffer_id_ = kInvalidId;
220 tracker_of_last_resort->second->set_dimensions(dimensions);
221 tracker_of_last_resort->second->set_held_by_producer(true);
222 return tracker_of_last_resort->first;
223 }
224 if (tracker_to_drop == trackers_.end()) {
225 // We're out of space, and can't find an unused tracker to reallocate.
226 return kInvalidId;
227 }
228 if (tracker_to_drop->first == last_relinquished_buffer_id_)
229 last_relinquished_buffer_id_ = kInvalidId;
230 *buffer_id_to_drop = tracker_to_drop->first;
231 delete tracker_to_drop->second;
232 trackers_.erase(tracker_to_drop);
233 }
234
235 // Create the new tracker.
236 const int buffer_id = next_buffer_id_++;
237
238 std::unique_ptr<VideoCaptureBufferTracker> tracker =
239 VideoCaptureBufferTrackerFactory::CreateTracker(storage_type);
240 // TODO(emircan): We pass the lock here to solve GMB allocation issue, see
241 // crbug.com/545238.
242 if (!tracker->Init(dimensions, pixel_format, storage_type, &lock_)) {
243 DLOG(ERROR) << "Error initializing VideoCaptureBufferTracker";
244 return kInvalidId;
245 }
246
247 tracker->set_held_by_producer(true);
248 trackers_[buffer_id] = tracker.release();
249
250 return buffer_id;
251 }
252
253 VideoCaptureBufferTracker* VideoCaptureBufferPoolImpl::GetTracker(
254 int buffer_id) {
255 TrackerMap::const_iterator it = trackers_.find(buffer_id);
256 return (it == trackers_.end()) ? NULL : it->second;
257 }
258
259 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698