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/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" | 10 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" |
11 #include "content/common/gpu/client/gpu_memory_buffer_impl.h" | 11 #include "content/common/gpu/client/gpu_memory_buffer_impl.h" |
12 #include "content/public/browser/browser_thread.h" | 12 #include "content/public/browser/browser_thread.h" |
13 #include "media/base/video_frame.h" | 13 #include "media/base/video_frame.h" |
14 | 14 |
15 using media::VideoFrame; | 15 using media::VideoFrame; |
16 | 16 |
17 namespace content { | 17 namespace content { |
18 | 18 |
19 const int VideoCaptureBufferPool::kInvalidId = -1; | 19 const int VideoCaptureBufferPool::kInvalidId = -1; |
20 | 20 |
21 VideoFrame::Format VideoPixelFormatToVideoFrameFormat( | 21 VideoFrame::Format VideoPixelFormatToVideoFrameFormat( |
22 media::VideoPixelFormat pixel_format) { | 22 media::VideoPixelFormat pixel_format) { |
23 static struct { | 23 static struct { |
24 media::VideoPixelFormat pixel_format; | 24 media::VideoPixelFormat pixel_format; |
25 VideoFrame::Format frame_format; | 25 VideoFrame::Format frame_format; |
26 } const kVideoPixelFormatToVideoFrameFormat[] = { | 26 } const kVideoPixelFormatToVideoFrameFormat[] = { |
27 {media::PIXEL_FORMAT_I420, VideoFrame::I420}, | 27 {media::PIXEL_FORMAT_I420, VideoFrame::I420}, |
28 {media::PIXEL_FORMAT_TEXTURE, VideoFrame::NATIVE_TEXTURE}, | 28 {media::PIXEL_FORMAT_TEXTURE, VideoFrame::ARGB}, |
29 {media::PIXEL_FORMAT_GPUMEMORYBUFFER, VideoFrame::NATIVE_TEXTURE}, | 29 {media::PIXEL_FORMAT_GPUMEMORYBUFFER, VideoFrame::ARGB}, |
30 }; | 30 }; |
31 | 31 |
32 for (const auto& format_pair : kVideoPixelFormatToVideoFrameFormat) { | 32 for (const auto& format_pair : kVideoPixelFormatToVideoFrameFormat) { |
33 if (format_pair.pixel_format == pixel_format) | 33 if (format_pair.pixel_format == pixel_format) |
34 return format_pair.frame_format; | 34 return format_pair.frame_format; |
35 } | 35 } |
36 LOG(ERROR) << "Unsupported VideoPixelFormat " | 36 LOG(ERROR) << "Unsupported VideoPixelFormat " |
37 << media::VideoCaptureFormat::PixelFormatToString(pixel_format); | 37 << media::VideoCaptureFormat::PixelFormatToString(pixel_format); |
38 return VideoFrame::UNKNOWN; | 38 return VideoFrame::UNKNOWN; |
39 } | 39 } |
40 | 40 |
| 41 VideoFrame::StorageType VideoPixelFormatToVideoFrameStorageType( |
| 42 media::VideoPixelFormat pixel_format) { |
| 43 static struct { |
| 44 media::VideoPixelFormat pixel_format; |
| 45 VideoFrame::StorageType storage_type; |
| 46 } const kVideoPixelFormatToVideoFrameStorageType[] = { |
| 47 {media::PIXEL_FORMAT_I420, VideoFrame::STORAGE_SHMEM}, |
| 48 {media::PIXEL_FORMAT_TEXTURE, VideoFrame::STORAGE_TEXTURE}, |
| 49 {media::PIXEL_FORMAT_GPUMEMORYBUFFER, VideoFrame::STORAGE_TEXTURE}, |
| 50 }; |
| 51 |
| 52 for (const auto& format_pair : kVideoPixelFormatToVideoFrameStorageType) { |
| 53 if (format_pair.pixel_format == pixel_format) |
| 54 return format_pair.storage_type; |
| 55 } |
| 56 LOG(ERROR) << "Unsupported VideoPixelFormat " |
| 57 << media::VideoCaptureFormat::PixelFormatToString(pixel_format); |
| 58 return VideoFrame::STORAGE_UNKNOWN; |
| 59 } |
| 60 |
41 // A simple holder of a memory-backed buffer and accesors to it. | 61 // A simple holder of a memory-backed buffer and accesors to it. |
42 class SimpleBufferHandle final : public VideoCaptureBufferPool::BufferHandle { | 62 class SimpleBufferHandle final : public VideoCaptureBufferPool::BufferHandle { |
43 public: | 63 public: |
44 SimpleBufferHandle(void* data, size_t size) : data_(data), size_(size) {} | 64 SimpleBufferHandle(void* data, size_t size) : data_(data), size_(size) {} |
45 ~SimpleBufferHandle() override {} | 65 ~SimpleBufferHandle() override {} |
46 | 66 |
47 size_t size() const override { return size_; } | 67 size_t size() const override { return size_; } |
48 void* data() override { return data_; } | 68 void* data() override { return data_; } |
49 gfx::GpuMemoryBufferType GetType() override { | 69 gfx::GpuMemoryBufferType GetType() override { |
50 return gfx::SHARED_MEMORY_BUFFER; | 70 return gfx::SHARED_MEMORY_BUFFER; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 private: | 103 private: |
84 gfx::GpuMemoryBuffer* const gmb_; | 104 gfx::GpuMemoryBuffer* const gmb_; |
85 scoped_ptr<void*[]> data_; | 105 scoped_ptr<void*[]> data_; |
86 const size_t size_; | 106 const size_t size_; |
87 }; | 107 }; |
88 | 108 |
89 // Tracker specifics for SharedMemory. | 109 // Tracker specifics for SharedMemory. |
90 class VideoCaptureBufferPool::SharedMemTracker final : public Tracker { | 110 class VideoCaptureBufferPool::SharedMemTracker final : public Tracker { |
91 public: | 111 public: |
92 SharedMemTracker(); | 112 SharedMemTracker(); |
93 bool Init(VideoFrame::Format format, const gfx::Size& dimensions) override; | 113 bool Init(VideoFrame::Format format, |
| 114 media::VideoFrame::StorageType storage_type, |
| 115 const gfx::Size& dimensions) override; |
94 | 116 |
95 size_t mapped_size() const override { return shared_memory_.mapped_size(); } | 117 size_t mapped_size() const override { return shared_memory_.mapped_size(); } |
96 | 118 |
97 scoped_ptr<BufferHandle> GetBufferHandle() override { | 119 scoped_ptr<BufferHandle> GetBufferHandle() override { |
98 return make_scoped_ptr( | 120 return make_scoped_ptr( |
99 new SimpleBufferHandle(shared_memory_.memory(), mapped_size())); | 121 new SimpleBufferHandle(shared_memory_.memory(), mapped_size())); |
100 } | 122 } |
101 | 123 |
102 bool ShareToProcess(base::ProcessHandle process_handle, | 124 bool ShareToProcess(base::ProcessHandle process_handle, |
103 base::SharedMemoryHandle* new_handle) override { | 125 base::SharedMemoryHandle* new_handle) override { |
104 return shared_memory_.ShareToProcess(process_handle, new_handle); | 126 return shared_memory_.ShareToProcess(process_handle, new_handle); |
105 } | 127 } |
106 | 128 |
107 private: | 129 private: |
108 // The memory created to be shared with renderer processes. | 130 // The memory created to be shared with renderer processes. |
109 base::SharedMemory shared_memory_; | 131 base::SharedMemory shared_memory_; |
110 }; | 132 }; |
111 | 133 |
112 // Tracker specifics for GpuMemoryBuffer. Owns one GpuMemoryBuffer and its | 134 // Tracker specifics for GpuMemoryBuffer. Owns one GpuMemoryBuffer and its |
113 // associated pixel dimensions. | 135 // associated pixel dimensions. |
114 class VideoCaptureBufferPool::GpuMemoryBufferTracker final : public Tracker { | 136 class VideoCaptureBufferPool::GpuMemoryBufferTracker final : public Tracker { |
115 public: | 137 public: |
116 GpuMemoryBufferTracker(); | 138 GpuMemoryBufferTracker(); |
117 bool Init(VideoFrame::Format format, const gfx::Size& dimensions) override; | 139 bool Init(VideoFrame::Format format, |
| 140 media::VideoFrame::StorageType storage_type, |
| 141 const gfx::Size& dimensions) override; |
118 ~GpuMemoryBufferTracker() override; | 142 ~GpuMemoryBufferTracker() override; |
119 | 143 |
120 size_t mapped_size() const override { return packed_size_; } | 144 size_t mapped_size() const override { return packed_size_; } |
121 scoped_ptr<BufferHandle> GetBufferHandle() override { | 145 scoped_ptr<BufferHandle> GetBufferHandle() override { |
122 return make_scoped_ptr(new GpuMemoryBufferBufferHandle( | 146 return make_scoped_ptr(new GpuMemoryBufferBufferHandle( |
123 gpu_memory_buffer_.get(), packed_size_)); | 147 gpu_memory_buffer_.get(), packed_size_)); |
124 } | 148 } |
125 | 149 |
126 bool ShareToProcess(base::ProcessHandle process_handle, | 150 bool ShareToProcess(base::ProcessHandle process_handle, |
127 base::SharedMemoryHandle* new_handle) override { | 151 base::SharedMemoryHandle* new_handle) override { |
128 return true; | 152 return true; |
129 } | 153 } |
130 | 154 |
131 private: | 155 private: |
132 size_t packed_size_; | 156 size_t packed_size_; |
133 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_; | 157 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_; |
134 }; | 158 }; |
135 | 159 |
136 VideoCaptureBufferPool::SharedMemTracker::SharedMemTracker() : Tracker() { | 160 VideoCaptureBufferPool::SharedMemTracker::SharedMemTracker() : Tracker() { |
137 } | 161 } |
138 | 162 |
139 bool VideoCaptureBufferPool::SharedMemTracker::Init( | 163 bool VideoCaptureBufferPool::SharedMemTracker::Init( |
140 VideoFrame::Format format, | 164 VideoFrame::Format format, |
| 165 media::VideoFrame::StorageType storage_type, |
141 const gfx::Size& dimensions) { | 166 const gfx::Size& dimensions) { |
142 DVLOG(2) << "allocating ShMem of " << dimensions.ToString(); | 167 DVLOG(2) << "allocating ShMem of " << dimensions.ToString(); |
143 set_pixel_format(format); | 168 set_pixel_format(format); |
| 169 set_storage_type(storage_type); |
144 // Input |dimensions| can be 0x0 for trackers that do not require memory | 170 // Input |dimensions| can be 0x0 for trackers that do not require memory |
145 // backing. The allocated size is calculated using VideoFrame methods since | 171 // backing. The allocated size is calculated using VideoFrame methods since |
146 // this will be the abstraction used to wrap the underlying data. | 172 // this will be the abstraction used to wrap the underlying data. |
147 set_pixel_count(dimensions.GetArea()); | 173 set_pixel_count(dimensions.GetArea()); |
148 const size_t byte_count = VideoFrame::AllocationSize(format, dimensions); | 174 const size_t byte_count = VideoFrame::AllocationSize(format, dimensions); |
149 if (!byte_count) | 175 if (!byte_count) |
150 return true; | 176 return true; |
151 return shared_memory_.CreateAndMapAnonymous(byte_count); | 177 return shared_memory_.CreateAndMapAnonymous(byte_count); |
152 } | 178 } |
153 | 179 |
154 VideoCaptureBufferPool::GpuMemoryBufferTracker::GpuMemoryBufferTracker() | 180 VideoCaptureBufferPool::GpuMemoryBufferTracker::GpuMemoryBufferTracker() |
155 : Tracker(), gpu_memory_buffer_(nullptr) {} | 181 : Tracker(), gpu_memory_buffer_(nullptr) {} |
156 | 182 |
157 VideoCaptureBufferPool::GpuMemoryBufferTracker::~GpuMemoryBufferTracker() { | 183 VideoCaptureBufferPool::GpuMemoryBufferTracker::~GpuMemoryBufferTracker() { |
158 if (gpu_memory_buffer_->IsMapped()) | 184 if (gpu_memory_buffer_->IsMapped()) |
159 gpu_memory_buffer_->Unmap(); | 185 gpu_memory_buffer_->Unmap(); |
160 } | 186 } |
161 | 187 |
162 bool VideoCaptureBufferPool::GpuMemoryBufferTracker::Init( | 188 bool VideoCaptureBufferPool::GpuMemoryBufferTracker::Init( |
163 VideoFrame::Format format, | 189 VideoFrame::Format format, |
| 190 media::VideoFrame::StorageType storage_type, |
164 const gfx::Size& dimensions) { | 191 const gfx::Size& dimensions) { |
165 DVLOG(2) << "allocating GMB for " << dimensions.ToString(); | 192 DVLOG(2) << "allocating GMB for " << dimensions.ToString(); |
166 // BrowserGpuMemoryBufferManager::current() may not be accessed on IO Thread. | 193 // BrowserGpuMemoryBufferManager::current() may not be accessed on IO Thread. |
167 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); | 194 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); |
168 DCHECK(BrowserGpuMemoryBufferManager::current()); | 195 DCHECK(BrowserGpuMemoryBufferManager::current()); |
169 set_pixel_format(format); | 196 set_pixel_format(format); |
| 197 set_storage_type(storage_type); |
170 set_pixel_count(dimensions.GetArea()); | 198 set_pixel_count(dimensions.GetArea()); |
171 gpu_memory_buffer_ = | 199 gpu_memory_buffer_ = |
172 BrowserGpuMemoryBufferManager::current()->AllocateGpuMemoryBuffer( | 200 BrowserGpuMemoryBufferManager::current()->AllocateGpuMemoryBuffer( |
173 dimensions, | 201 dimensions, |
174 gfx::GpuMemoryBuffer::BGRA_8888, | 202 gfx::GpuMemoryBuffer::BGRA_8888, |
175 gfx::GpuMemoryBuffer::MAP); | 203 gfx::GpuMemoryBuffer::MAP); |
176 DLOG_IF(ERROR, !gpu_memory_buffer_.get()) << "Allocating GpuMemoryBuffer"; | 204 DLOG_IF(ERROR, !gpu_memory_buffer_.get()) << "Allocating GpuMemoryBuffer"; |
177 if (!gpu_memory_buffer_.get()) | 205 if (!gpu_memory_buffer_.get()) |
178 return false; | 206 return false; |
179 int plane_sizes; | 207 int plane_sizes; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 media::VideoPixelFormat format, | 319 media::VideoPixelFormat format, |
292 const gfx::Size& dimensions, | 320 const gfx::Size& dimensions, |
293 int* buffer_id_to_drop) { | 321 int* buffer_id_to_drop) { |
294 DCHECK(format == media::PIXEL_FORMAT_I420 || | 322 DCHECK(format == media::PIXEL_FORMAT_I420 || |
295 format == media::PIXEL_FORMAT_TEXTURE || | 323 format == media::PIXEL_FORMAT_TEXTURE || |
296 format == media::PIXEL_FORMAT_GPUMEMORYBUFFER ); | 324 format == media::PIXEL_FORMAT_GPUMEMORYBUFFER ); |
297 lock_.AssertAcquired(); | 325 lock_.AssertAcquired(); |
298 *buffer_id_to_drop = kInvalidId; | 326 *buffer_id_to_drop = kInvalidId; |
299 | 327 |
300 const size_t size_in_pixels = dimensions.GetArea(); | 328 const size_t size_in_pixels = dimensions.GetArea(); |
| 329 const media::VideoFrame::Format pixel_format = |
| 330 VideoPixelFormatToVideoFrameFormat(format); |
| 331 const media::VideoFrame::StorageType storage_type = |
| 332 VideoPixelFormatToVideoFrameStorageType(format); |
301 // Look for a tracker that's allocated, big enough, and not in use. Track the | 333 // Look for a tracker that's allocated, big enough, and not in use. Track the |
302 // largest one that's not big enough, in case we have to reallocate a tracker. | 334 // largest one that's not big enough, in case we have to reallocate a tracker. |
303 *buffer_id_to_drop = kInvalidId; | 335 *buffer_id_to_drop = kInvalidId; |
304 size_t largest_size_in_pixels = 0; | 336 size_t largest_size_in_pixels = 0; |
305 TrackerMap::iterator tracker_to_drop = trackers_.end(); | 337 TrackerMap::iterator tracker_to_drop = trackers_.end(); |
306 for (TrackerMap::iterator it = trackers_.begin(); it != trackers_.end(); | 338 for (TrackerMap::iterator it = trackers_.begin(); it != trackers_.end(); |
307 ++it) { | 339 ++it) { |
308 Tracker* const tracker = it->second; | 340 Tracker* const tracker = it->second; |
309 if (!tracker->consumer_hold_count() && !tracker->held_by_producer()) { | 341 if (!tracker->consumer_hold_count() && !tracker->held_by_producer()) { |
310 if (tracker->pixel_count() >= size_in_pixels && | 342 if (tracker->pixel_count() >= size_in_pixels && |
311 (tracker->pixel_format() == | 343 (tracker->pixel_format() == pixel_format) && |
312 VideoPixelFormatToVideoFrameFormat(format))) { | 344 (tracker->storage_type() == storage_type)) { |
313 // Existing tracker is big enough and has correct format. Reuse it. | 345 // Existing tracker is big enough and has correct format. Reuse it. |
314 tracker->set_held_by_producer(true); | 346 tracker->set_held_by_producer(true); |
315 return it->first; | 347 return it->first; |
316 } | 348 } |
317 if (tracker->pixel_count() > largest_size_in_pixels) { | 349 if (tracker->pixel_count() > largest_size_in_pixels) { |
318 largest_size_in_pixels = tracker->pixel_count(); | 350 largest_size_in_pixels = tracker->pixel_count(); |
319 tracker_to_drop = it; | 351 tracker_to_drop = it; |
320 } | 352 } |
321 } | 353 } |
322 } | 354 } |
323 | 355 |
324 // Preferably grow the pool by creating a new tracker. If we're at maximum | 356 // Preferably grow the pool by creating a new tracker. If we're at maximum |
325 // size, then reallocate by deleting an existing one instead. | 357 // size, then reallocate by deleting an existing one instead. |
326 if (trackers_.size() == static_cast<size_t>(count_)) { | 358 if (trackers_.size() == static_cast<size_t>(count_)) { |
327 if (tracker_to_drop == trackers_.end()) { | 359 if (tracker_to_drop == trackers_.end()) { |
328 // We're out of space, and can't find an unused tracker to reallocate. | 360 // We're out of space, and can't find an unused tracker to reallocate. |
329 return kInvalidId; | 361 return kInvalidId; |
330 } | 362 } |
331 *buffer_id_to_drop = tracker_to_drop->first; | 363 *buffer_id_to_drop = tracker_to_drop->first; |
332 delete tracker_to_drop->second; | 364 delete tracker_to_drop->second; |
333 trackers_.erase(tracker_to_drop); | 365 trackers_.erase(tracker_to_drop); |
334 } | 366 } |
335 | 367 |
336 // Create the new tracker. | 368 // Create the new tracker. |
337 const int buffer_id = next_buffer_id_++; | 369 const int buffer_id = next_buffer_id_++; |
338 | 370 |
339 scoped_ptr<Tracker> tracker = | 371 scoped_ptr<Tracker> tracker = |
340 Tracker::CreateTracker(format == media::PIXEL_FORMAT_GPUMEMORYBUFFER); | 372 Tracker::CreateTracker(format == media::PIXEL_FORMAT_GPUMEMORYBUFFER); |
341 if (!tracker->Init(VideoPixelFormatToVideoFrameFormat(format), dimensions)) { | 373 if (!tracker->Init(pixel_format, storage_type, dimensions)) { |
342 DLOG(ERROR) << "Error initializing Tracker"; | 374 DLOG(ERROR) << "Error initializing Tracker"; |
343 return kInvalidId; | 375 return kInvalidId; |
344 } | 376 } |
345 tracker->set_held_by_producer(true); | 377 tracker->set_held_by_producer(true); |
346 trackers_[buffer_id] = tracker.release(); | 378 trackers_[buffer_id] = tracker.release(); |
347 | 379 |
348 return buffer_id; | 380 return buffer_id; |
349 } | 381 } |
350 | 382 |
351 VideoCaptureBufferPool::Tracker* VideoCaptureBufferPool::GetTracker( | 383 VideoCaptureBufferPool::Tracker* VideoCaptureBufferPool::GetTracker( |
352 int buffer_id) { | 384 int buffer_id) { |
353 TrackerMap::const_iterator it = trackers_.find(buffer_id); | 385 TrackerMap::const_iterator it = trackers_.find(buffer_id); |
354 return (it == trackers_.end()) ? NULL : it->second; | 386 return (it == trackers_.end()) ? NULL : it->second; |
355 } | 387 } |
356 | 388 |
357 } // namespace content | 389 } // namespace content |
OLD | NEW |