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

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

Issue 1090273006: Revert of VideoCapture: add support for GpuMemoryBuffer allocation and lifetime mgmt in VideoCaptureBufferPool (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/logging.h" 7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
11 #include "content/common/gpu/client/gpu_memory_buffer_impl.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "media/base/video_frame.h"
14 10
15 using media::VideoFrame; 11 using media::VideoFrame;
16 12
17 namespace content { 13 namespace content {
18 14
19 const int VideoCaptureBufferPool::kInvalidId = -1; 15 const int VideoCaptureBufferPool::kInvalidId = -1;
20 16
21 VideoFrame::Format VideoPixelFormatToVideoFrameFormat( 17 VideoFrame::Format VideoPixelFormatToVideoFrameFormat(
22 media::VideoPixelFormat pixel_format) { 18 media::VideoPixelFormat pixel_format) {
23 static struct { 19 static struct {
24 media::VideoPixelFormat pixel_format; 20 media::VideoPixelFormat pixel_format;
25 VideoFrame::Format frame_format; 21 VideoFrame::Format frame_format;
26 } const kVideoPixelFormatToVideoFrameFormat[] = { 22 } const kVideoPixelFormatToVideoFrameFormat[] = {
27 {media::PIXEL_FORMAT_I420, VideoFrame::I420}, 23 {media::PIXEL_FORMAT_I420, VideoFrame::I420},
24 {media::PIXEL_FORMAT_ARGB, VideoFrame::ARGB},
28 {media::PIXEL_FORMAT_TEXTURE, VideoFrame::NATIVE_TEXTURE}, 25 {media::PIXEL_FORMAT_TEXTURE, VideoFrame::NATIVE_TEXTURE},
29 {media::PIXEL_FORMAT_GPUMEMORYBUFFER, VideoFrame::NATIVE_TEXTURE},
30 }; 26 };
31 27
32 for (const auto& format_pair : kVideoPixelFormatToVideoFrameFormat) { 28 for (const auto& format_pair : kVideoPixelFormatToVideoFrameFormat) {
33 if (format_pair.pixel_format == pixel_format) 29 if (format_pair.pixel_format == pixel_format)
34 return format_pair.frame_format; 30 return format_pair.frame_format;
35 } 31 }
36 LOG(ERROR) << "Unsupported VideoPixelFormat " 32 LOG(ERROR) << "Unsupported VideoPixelFormat "
37 << media::VideoCaptureFormat::PixelFormatToString(pixel_format); 33 << media::VideoCaptureFormat::PixelFormatToString(pixel_format);
38 return VideoFrame::UNKNOWN; 34 return VideoFrame::UNKNOWN;
39 } 35 }
40 36
41 // A simple holder of a memory-backed buffer and accesors to it.
42 class SimpleBufferHandle final : public VideoCaptureBufferPool::BufferHandle {
43 public:
44 SimpleBufferHandle(void* data, size_t size) : data_(data), size_(size) {}
45 ~SimpleBufferHandle() override {}
46
47 size_t size() const override { return size_; }
48 void* data() override { return data_; }
49 ClientBuffer AsClientBuffer() override { return nullptr; }
50
51 private:
52 void* const data_;
53 const size_t size_;
54 };
55
56 // A holder of a GpuMemoryBuffer-backed buffer, Map()ed on ctor and Unmap()ed on
57 // dtor. Holds a weak reference to its GpuMemoryBuffer.
58 // TODO(mcasas) Map()ed on ctor, or on first use?
59 class GpuMemoryBufferBufferHandle
60 final : public VideoCaptureBufferPool::BufferHandle {
61 public:
62 GpuMemoryBufferBufferHandle(gfx::GpuMemoryBuffer* gmb, size_t size)
63 : gmb_(gmb),
64 data_(new void* [GpuMemoryBufferImpl::
65 NumberOfPlanesForGpuMemoryBufferFormat(
66 gmb_->GetFormat())]),
67 size_(size) {
68 DCHECK(gmb && !gmb_->IsMapped());
69 gmb_->Map(data_.get());
70 }
71 ~GpuMemoryBufferBufferHandle() override { gmb_->Unmap(); }
72
73 size_t size() const override { return size_; }
74 void* data() override { return data_[0]; }
75 ClientBuffer AsClientBuffer() override { return gmb_->AsClientBuffer(); }
76
77 private:
78 gfx::GpuMemoryBuffer* const gmb_;
79 scoped_ptr<void*[]> data_;
80 const size_t size_;
81 };
82
83 // Tracker specifics for SharedMemory. 37 // Tracker specifics for SharedMemory.
84 class VideoCaptureBufferPool::SharedMemTracker final : public Tracker { 38 class VideoCaptureBufferPool::SharedMemTracker final : public Tracker {
85 public: 39 public:
86 SharedMemTracker(); 40 SharedMemTracker();
41
87 bool Init(VideoFrame::Format format, const gfx::Size& dimensions) override; 42 bool Init(VideoFrame::Format format, const gfx::Size& dimensions) override;
88 43 void* storage() override { return shared_memory_.memory(); }
89 size_t mapped_size() const override { return shared_memory_.mapped_size(); } 44 size_t requested_size() override { return shared_memory_.requested_size(); }
90 45 size_t mapped_size() override { return shared_memory_.mapped_size(); }
91 scoped_ptr<BufferHandle> GetBufferHandle() override {
92 return make_scoped_ptr(
93 new SimpleBufferHandle(shared_memory_.memory(), mapped_size()));
94 }
95 46
96 bool ShareToProcess(base::ProcessHandle process_handle, 47 bool ShareToProcess(base::ProcessHandle process_handle,
97 base::SharedMemoryHandle* new_handle) override { 48 base::SharedMemoryHandle* new_handle) override {
98 return shared_memory_.ShareToProcess(process_handle, new_handle); 49 return shared_memory_.ShareToProcess(process_handle, new_handle);
99 } 50 }
100 51
101 private: 52 private:
102 // The memory created to be shared with renderer processes. 53 // The memory created to be shared with renderer processes.
103 base::SharedMemory shared_memory_; 54 base::SharedMemory shared_memory_;
104 }; 55 };
105 56
106 // Tracker specifics for GpuMemoryBuffer. Owns one GpuMemoryBuffer and its 57 VideoCaptureBufferPool::SharedMemTracker::SharedMemTracker()
107 // associated pixel dimensions. 58 : Tracker() {}
108 class VideoCaptureBufferPool::GpuMemoryBufferTracker final : public Tracker {
109 public:
110 GpuMemoryBufferTracker();
111 bool Init(VideoFrame::Format format, const gfx::Size& dimensions) override;
112 ~GpuMemoryBufferTracker() override;
113
114 size_t mapped_size() const override { return packed_size_; }
115 scoped_ptr<BufferHandle> GetBufferHandle() override {
116 return make_scoped_ptr(new GpuMemoryBufferBufferHandle(
117 gpu_memory_buffer_.get(), packed_size_));
118 }
119
120 bool ShareToProcess(base::ProcessHandle process_handle,
121 base::SharedMemoryHandle* new_handle) override {
122 return true;
123 }
124
125 private:
126 size_t packed_size_;
127 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_;
128 };
129
130 VideoCaptureBufferPool::SharedMemTracker::SharedMemTracker() : Tracker() {
131 }
132 59
133 bool VideoCaptureBufferPool::SharedMemTracker::Init( 60 bool VideoCaptureBufferPool::SharedMemTracker::Init(
134 VideoFrame::Format format, 61 VideoFrame::Format format,
135 const gfx::Size& dimensions) { 62 const gfx::Size& dimensions) {
136 DVLOG(2) << "allocating ShMem of " << dimensions.ToString();
137 // Input |dimensions| can be 0x0 for trackers that do not require memory 63 // Input |dimensions| can be 0x0 for trackers that do not require memory
138 // backing. The allocated size is calculated using VideoFrame methods since 64 // backing. The allocated size is calculated using VideoFrame methods since
139 // this will be the abstraction used to wrap the underlying data. 65 // this will be the abstraction used to wrap the underlying data.
140 set_pixel_count(dimensions.GetArea()); 66 return shared_memory_.CreateAndMapAnonymous(
141 const size_t byte_count = VideoFrame::AllocationSize(format, dimensions); 67 VideoFrame::AllocationSize(format, dimensions));
142 if (!byte_count)
143 return true;
144 return shared_memory_.CreateAndMapAnonymous(byte_count);
145 }
146
147 VideoCaptureBufferPool::GpuMemoryBufferTracker::GpuMemoryBufferTracker()
148 : Tracker(), gpu_memory_buffer_(nullptr) {}
149
150 VideoCaptureBufferPool::GpuMemoryBufferTracker::~GpuMemoryBufferTracker() {
151 if (gpu_memory_buffer_->IsMapped())
152 gpu_memory_buffer_->Unmap();
153 }
154
155 bool VideoCaptureBufferPool::GpuMemoryBufferTracker::Init(
156 VideoFrame::Format format,
157 const gfx::Size& dimensions) {
158 DVLOG(2) << "allocating GMB for " << dimensions.ToString();
159 // BrowserGpuMemoryBufferManager::current() may not be accessed on IO Thread.
160 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
161 DCHECK(BrowserGpuMemoryBufferManager::current());
162 set_pixel_count(dimensions.GetArea());
163 gpu_memory_buffer_ =
164 BrowserGpuMemoryBufferManager::current()->AllocateGpuMemoryBuffer(
165 dimensions,
166 gfx::GpuMemoryBuffer::BGRA_8888,
167 gfx::GpuMemoryBuffer::MAP);
168 DLOG_IF(ERROR, !gpu_memory_buffer_.get()) << "Allocating GpuMemoryBuffer";
169 if (!gpu_memory_buffer_.get())
170 return false;
171 int plane_sizes;
172 gpu_memory_buffer_->GetStride(&plane_sizes);
173 packed_size_ = plane_sizes * dimensions.height();
174 return true;
175 } 68 }
176 69
177 //static 70 //static
178 scoped_ptr<VideoCaptureBufferPool::Tracker> 71 scoped_ptr<VideoCaptureBufferPool::Tracker>
179 VideoCaptureBufferPool::Tracker::CreateTracker(bool use_gmb) { 72 VideoCaptureBufferPool::Tracker::CreateTracker() {
180 if (!use_gmb) 73 return make_scoped_ptr(new SharedMemTracker());
181 return make_scoped_ptr(new SharedMemTracker());
182 else
183 return make_scoped_ptr(new GpuMemoryBufferTracker());
184 } 74 }
185 75
186 VideoCaptureBufferPool::Tracker::~Tracker() {} 76 VideoCaptureBufferPool::Tracker::~Tracker() {}
187 77
188 VideoCaptureBufferPool::VideoCaptureBufferPool(int count) 78 VideoCaptureBufferPool::VideoCaptureBufferPool(int count)
189 : count_(count), 79 : count_(count),
190 next_buffer_id_(0) { 80 next_buffer_id_(0) {
191 DCHECK_GT(count, 0); 81 DCHECK_GT(count, 0);
192 } 82 }
193 83
(...skipping 10 matching lines...) Expand all
204 Tracker* tracker = GetTracker(buffer_id); 94 Tracker* tracker = GetTracker(buffer_id);
205 if (!tracker) { 95 if (!tracker) {
206 NOTREACHED() << "Invalid buffer_id."; 96 NOTREACHED() << "Invalid buffer_id.";
207 return base::SharedMemory::NULLHandle(); 97 return base::SharedMemory::NULLHandle();
208 } 98 }
209 base::SharedMemoryHandle remote_handle; 99 base::SharedMemoryHandle remote_handle;
210 if (tracker->ShareToProcess(process_handle, &remote_handle)) { 100 if (tracker->ShareToProcess(process_handle, &remote_handle)) {
211 *memory_size = tracker->mapped_size(); 101 *memory_size = tracker->mapped_size();
212 return remote_handle; 102 return remote_handle;
213 } 103 }
214 DPLOG(ERROR) << "Error mapping Shared Memory"; 104 DPLOG(ERROR) << "Error mapping Shared Memory.";
215 return base::SharedMemoryHandle(); 105 return base::SharedMemoryHandle();
216 } 106 }
217 107
218 scoped_ptr<VideoCaptureBufferPool::BufferHandle> 108 bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id,
219 VideoCaptureBufferPool::GetBufferHandle(int buffer_id) { 109 void** storage,
110 size_t* size) {
220 base::AutoLock lock(lock_); 111 base::AutoLock lock(lock_);
221 112
222 Tracker* tracker = GetTracker(buffer_id); 113 Tracker* tracker = GetTracker(buffer_id);
223 if (!tracker) { 114 if (!tracker) {
224 NOTREACHED() << "Invalid buffer_id."; 115 NOTREACHED() << "Invalid buffer_id.";
225 return scoped_ptr<BufferHandle>(); 116 return false;
226 } 117 }
227 118
228 DCHECK(tracker->held_by_producer()); 119 DCHECK(tracker->held_by_producer());
229 return tracker->GetBufferHandle(); 120 *storage = tracker->storage();
121 *size = tracker->mapped_size();
122 return true;
230 } 123 }
231 124
232 int VideoCaptureBufferPool::ReserveForProducer(media::VideoPixelFormat format, 125 int VideoCaptureBufferPool::ReserveForProducer(media::VideoPixelFormat format,
233 const gfx::Size& dimensions, 126 const gfx::Size& dimensions,
234 int* buffer_id_to_drop) { 127 int* buffer_id_to_drop) {
235 base::AutoLock lock(lock_); 128 base::AutoLock lock(lock_);
236 return ReserveForProducerInternal(format, dimensions, buffer_id_to_drop); 129 return ReserveForProducerInternal(format, dimensions, buffer_id_to_drop);
237 } 130 }
238 131
239 void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) { 132 void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 170
278 tracker->set_consumer_hold_count(tracker->consumer_hold_count() - 171 tracker->set_consumer_hold_count(tracker->consumer_hold_count() -
279 num_clients); 172 num_clients);
280 } 173 }
281 174
282 int VideoCaptureBufferPool::ReserveForProducerInternal( 175 int VideoCaptureBufferPool::ReserveForProducerInternal(
283 media::VideoPixelFormat format, 176 media::VideoPixelFormat format,
284 const gfx::Size& dimensions, 177 const gfx::Size& dimensions,
285 int* buffer_id_to_drop) { 178 int* buffer_id_to_drop) {
286 DCHECK(format == media::PIXEL_FORMAT_I420 || 179 DCHECK(format == media::PIXEL_FORMAT_I420 ||
287 format == media::PIXEL_FORMAT_TEXTURE || 180 format == media::PIXEL_FORMAT_ARGB ||
288 format == media::PIXEL_FORMAT_GPUMEMORYBUFFER ); 181 format == media::PIXEL_FORMAT_TEXTURE);
289 lock_.AssertAcquired(); 182 lock_.AssertAcquired();
290 *buffer_id_to_drop = kInvalidId; 183 const media::VideoFrame::Format frame_format =
184 VideoPixelFormatToVideoFrameFormat(format);
185 const size_t size_in_bytes =
186 VideoFrame::AllocationSize(frame_format, dimensions);
291 187
292 const size_t size_in_pixels = dimensions.GetArea();
293 // Look for a tracker that's allocated, big enough, and not in use. Track the 188 // Look for a tracker that's allocated, big enough, and not in use. Track the
294 // largest one that's not big enough, in case we have to reallocate a tracker. 189 // largest one that's not big enough, in case we have to reallocate a tracker.
295 *buffer_id_to_drop = kInvalidId; 190 *buffer_id_to_drop = kInvalidId;
296 size_t largest_size_in_pixels = 0; 191 size_t realloc_size = 0;
297 TrackerMap::iterator tracker_to_drop = trackers_.end(); 192 TrackerMap::iterator tracker_to_drop = trackers_.end();
298 for (TrackerMap::iterator it = trackers_.begin(); it != trackers_.end(); 193 for (TrackerMap::iterator it = trackers_.begin(); it != trackers_.end();
299 ++it) { 194 ++it) {
300 Tracker* const tracker = it->second; 195 Tracker* const tracker = it->second;
301 if (!tracker->consumer_hold_count() && !tracker->held_by_producer()) { 196 if (!tracker->consumer_hold_count() && !tracker->held_by_producer()) {
302 if (tracker->pixel_count() >= size_in_pixels) { 197 if (tracker->requested_size() >= size_in_bytes) {
303 // Existing tracker is big enough. Reuse it. 198 // Existing tracker is big enough. Reuse it.
304 tracker->set_held_by_producer(true); 199 tracker->set_held_by_producer(true);
305 return it->first; 200 return it->first;
306 } 201 }
307 if (tracker->pixel_count() > largest_size_in_pixels) { 202 if (tracker->requested_size() > realloc_size) {
308 largest_size_in_pixels = tracker->pixel_count(); 203 realloc_size = tracker->requested_size();
309 tracker_to_drop = it; 204 tracker_to_drop = it;
310 } 205 }
311 } 206 }
312 } 207 }
313 208
314 // Preferably grow the pool by creating a new tracker. If we're at maximum 209 // Preferably grow the pool by creating a new tracker. If we're at maximum
315 // size, then reallocate by deleting an existing one instead. 210 // size, then reallocate by deleting an existing one instead.
316 if (trackers_.size() == static_cast<size_t>(count_)) { 211 if (trackers_.size() == static_cast<size_t>(count_)) {
317 if (tracker_to_drop == trackers_.end()) { 212 if (tracker_to_drop == trackers_.end()) {
318 // We're out of space, and can't find an unused tracker to reallocate. 213 // We're out of space, and can't find an unused tracker to reallocate.
319 return kInvalidId; 214 return kInvalidId;
320 } 215 }
321 *buffer_id_to_drop = tracker_to_drop->first; 216 *buffer_id_to_drop = tracker_to_drop->first;
322 delete tracker_to_drop->second; 217 delete tracker_to_drop->second;
323 trackers_.erase(tracker_to_drop); 218 trackers_.erase(tracker_to_drop);
324 } 219 }
325 220
326 // Create the new tracker. 221 // Create the new tracker.
327 const int buffer_id = next_buffer_id_++; 222 const int buffer_id = next_buffer_id_++;
328 223 scoped_ptr<Tracker> tracker = Tracker::CreateTracker();
329 scoped_ptr<Tracker> tracker = 224 if (!tracker->Init(frame_format, dimensions))
330 Tracker::CreateTracker(format == media::PIXEL_FORMAT_GPUMEMORYBUFFER);
331 if (!tracker->Init(VideoPixelFormatToVideoFrameFormat(format), dimensions)) {
332 DLOG(ERROR) << "Error initializing Tracker";
333 return kInvalidId; 225 return kInvalidId;
334 }
335 tracker->set_held_by_producer(true); 226 tracker->set_held_by_producer(true);
336 trackers_[buffer_id] = tracker.release(); 227 trackers_[buffer_id] = tracker.release();
337 228
338 return buffer_id; 229 return buffer_id;
339 } 230 }
340 231
341 VideoCaptureBufferPool::Tracker* VideoCaptureBufferPool::GetTracker( 232 VideoCaptureBufferPool::Tracker* VideoCaptureBufferPool::GetTracker(
342 int buffer_id) { 233 int buffer_id) {
343 TrackerMap::const_iterator it = trackers_.find(buffer_id); 234 TrackerMap::const_iterator it = trackers_.find(buffer_id);
344 return (it == trackers_.end()) ? NULL : it->second; 235 return (it == trackers_.end()) ? NULL : it->second;
345 } 236 }
346 237
347 } // namespace content 238 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698