| 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 |