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

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: miu@s comments 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"
8 #include "base/callback.h"
9 #include "base/logging.h" 7 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
11 #include "base/stl_util.h" 9 #include "base/stl_util.h"
12 #include "media/base/video_frame.h" 10
13 #include "media/base/video_util.h" 11 using media::VideoFrame;
14 12
15 namespace content { 13 namespace content {
16 14
17 const int VideoCaptureBufferPool::kInvalidId = -1; 15 const int VideoCaptureBufferPool::kInvalidId = -1;
18 16
17 VideoFrame::Format VideoPixelFormatToVideoFrameFormat(
miu 2015/04/08 22:26:14 I seem to recall seeing this enum-mapping function
mcasas 2015/04/09 02:03:22 Perhaps you might be counting transforms between F
18 media::VideoPixelFormat pixel_format) {
19 static struct {
20 media::VideoPixelFormat pixel_format;
21 VideoFrame::Format frame_format;
22 } const kVideoFrameFormatToVideoPixelFormat[] = {
23 {media::PIXEL_FORMAT_I420, VideoFrame::I420},
24 {media::PIXEL_FORMAT_ARGB, VideoFrame::ARGB},
25 {media::PIXEL_FORMAT_TEXTURE, VideoFrame::NATIVE_TEXTURE},
26 };
27
28 for (const auto& format_pair : kVideoFrameFormatToVideoPixelFormat) {
miu 2015/04/08 22:26:14 Instead of iterating a static array, consider usin
mcasas 2015/04/09 02:03:22 Note that not all cases are contemplated here, onl
29 if (format_pair.pixel_format == pixel_format)
30 return format_pair.frame_format;
31 }
32 LOG(ERROR) << "Unsupported VideoPixelFormat "
33 << media::VideoCaptureFormat::PixelFormatToString(pixel_format);
34 return VideoFrame::UNKNOWN;
35 }
36
37 // Tracker specifics for SharedMemory.
38 class VideoCaptureBufferPool::SharedMemTracker final : public Tracker {
39 public:
40 SharedMemTracker();
41
42 bool Init(VideoFrame::Format format, const gfx::Size& dimensions) override;
43 void* storage() override { return shared_memory_.memory(); }
44 size_t requested_size() override { return shared_memory_.requested_size(); }
45 size_t mapped_size() override { return shared_memory_.mapped_size(); }
46
47 bool ShareToProcess(base::ProcessHandle process_handle,
48 base::SharedMemoryHandle* new_handle) override {
49 return shared_memory_.ShareToProcess(process_handle, new_handle);
50 }
51
52 private:
53 // The memory created to be shared with renderer processes.
54 base::SharedMemory shared_memory_;
55 };
56
57 VideoCaptureBufferPool::SharedMemTracker::SharedMemTracker()
58 : Tracker() {}
59
60 bool VideoCaptureBufferPool::SharedMemTracker::Init(
61 VideoFrame::Format format,
62 const gfx::Size& dimensions) {
63 // Input |dimensions| can be 0x0 for trackers that do not require memory
64 // backing. The allocated size is calculated using VideoFrame methods since
65 // this will be the abstraction used to wrap the underlying data.
66 return shared_memory_.CreateAndMapAnonymous(
67 VideoFrame::AllocationSize(format, dimensions));
68 }
69
70 //static
71 scoped_ptr<VideoCaptureBufferPool::Tracker>
72 VideoCaptureBufferPool::Tracker::CreateTracker() {
73 return make_scoped_ptr(new SharedMemTracker());
74 }
75
76 VideoCaptureBufferPool::Tracker::~Tracker() {}
77
19 VideoCaptureBufferPool::VideoCaptureBufferPool(int count) 78 VideoCaptureBufferPool::VideoCaptureBufferPool(int count)
20 : count_(count), 79 : count_(count),
21 next_buffer_id_(0) { 80 next_buffer_id_(0) {
22 DCHECK_GT(count, 0); 81 DCHECK_GT(count, 0);
23 } 82 }
24 83
25 VideoCaptureBufferPool::~VideoCaptureBufferPool() { 84 VideoCaptureBufferPool::~VideoCaptureBufferPool() {
26 STLDeleteValues(&buffers_); 85 STLDeleteValues(&trackers_);
27 } 86 }
28 87
29 base::SharedMemoryHandle VideoCaptureBufferPool::ShareToProcess( 88 base::SharedMemoryHandle VideoCaptureBufferPool::ShareToProcess(
30 int buffer_id, 89 int buffer_id,
31 base::ProcessHandle process_handle, 90 base::ProcessHandle process_handle,
32 size_t* memory_size) { 91 size_t* memory_size) {
33 base::AutoLock lock(lock_); 92 base::AutoLock lock(lock_);
34 93
35 Buffer* buffer = GetBuffer(buffer_id); 94 Tracker* tracker = GetTracker(buffer_id);
36 if (!buffer) { 95 if (!tracker) {
37 NOTREACHED() << "Invalid buffer_id."; 96 NOTREACHED() << "Invalid buffer_id.";
38 return base::SharedMemory::NULLHandle(); 97 return base::SharedMemory::NULLHandle();
39 } 98 }
40 base::SharedMemoryHandle remote_handle; 99 base::SharedMemoryHandle remote_handle;
41 buffer->shared_memory.ShareToProcess(process_handle, &remote_handle); 100 if (tracker->ShareToProcess(process_handle, &remote_handle)) {
42 *memory_size = buffer->shared_memory.requested_size(); 101 *memory_size = tracker->mapped_size();
43 return remote_handle; 102 return remote_handle;
103 }
104 DPLOG(ERROR) << "Error mapping Shared Memory.";
105 return base::SharedMemoryHandle();
44 } 106 }
45 107
46 bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id, 108 bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id,
47 void** memory, 109 void** storage,
48 size_t* size) { 110 size_t* size) {
49 base::AutoLock lock(lock_); 111 base::AutoLock lock(lock_);
50 112
51 Buffer* buffer = GetBuffer(buffer_id); 113 Tracker* tracker = GetTracker(buffer_id);
52 if (!buffer) { 114 if (!tracker) {
53 NOTREACHED() << "Invalid buffer_id."; 115 NOTREACHED() << "Invalid buffer_id.";
54 return false; 116 return false;
55 } 117 }
56 118
57 DCHECK(buffer->held_by_producer); 119 DCHECK(tracker->held_by_producer());
58 *memory = buffer->shared_memory.memory(); 120 *storage = tracker->storage();
59 *size = buffer->shared_memory.mapped_size(); 121 *size = tracker->mapped_size();
60 return true; 122 return true;
61 } 123 }
62 124
63 int VideoCaptureBufferPool::ReserveForProducer(size_t size, 125 int VideoCaptureBufferPool::ReserveForProducer(media::VideoPixelFormat format,
126 const gfx::Size& dimensions,
64 int* buffer_id_to_drop) { 127 int* buffer_id_to_drop) {
65 base::AutoLock lock(lock_); 128 base::AutoLock lock(lock_);
66 return ReserveForProducerInternal(size, buffer_id_to_drop); 129 return ReserveForProducerInternal(format, dimensions, buffer_id_to_drop);
67 } 130 }
68 131
69 void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) { 132 void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) {
70 base::AutoLock lock(lock_); 133 base::AutoLock lock(lock_);
71 Buffer* buffer = GetBuffer(buffer_id); 134 Tracker* tracker = GetTracker(buffer_id);
72 if (!buffer) { 135 if (!tracker) {
73 NOTREACHED() << "Invalid buffer_id."; 136 NOTREACHED() << "Invalid buffer_id.";
74 return; 137 return;
75 } 138 }
76 DCHECK(buffer->held_by_producer); 139 DCHECK(tracker->held_by_producer());
77 buffer->held_by_producer = false; 140 tracker->set_held_by_producer(false);
78 } 141 }
79 142
80 void VideoCaptureBufferPool::HoldForConsumers( 143 void VideoCaptureBufferPool::HoldForConsumers(
81 int buffer_id, 144 int buffer_id,
82 int num_clients) { 145 int num_clients) {
83 base::AutoLock lock(lock_); 146 base::AutoLock lock(lock_);
84 Buffer* buffer = GetBuffer(buffer_id); 147 Tracker* tracker = GetTracker(buffer_id);
85 if (!buffer) { 148 if (!tracker) {
86 NOTREACHED() << "Invalid buffer_id."; 149 NOTREACHED() << "Invalid buffer_id.";
87 return; 150 return;
88 } 151 }
89 DCHECK(buffer->held_by_producer); 152 DCHECK(tracker->held_by_producer());
90 DCHECK(!buffer->consumer_hold_count); 153 DCHECK(!tracker->consumer_hold_count());
91 154
92 buffer->consumer_hold_count = num_clients; 155 tracker->set_consumer_hold_count(num_clients);
93 // Note: |held_by_producer| will stay true until 156 // Note: |held_by_producer()| will stay true until
94 // RelinquishProducerReservation() (usually called by destructor of the object 157 // RelinquishProducerReservation() (usually called by destructor of the object
95 // wrapping this buffer, e.g. a media::VideoFrame). 158 // wrapping this tracker, e.g. a media::VideoFrame).
96 } 159 }
97 160
98 void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id, 161 void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id,
99 int num_clients) { 162 int num_clients) {
100 base::AutoLock lock(lock_); 163 base::AutoLock lock(lock_);
101 Buffer* buffer = GetBuffer(buffer_id); 164 Tracker* tracker = GetTracker(buffer_id);
102 if (!buffer) { 165 if (!tracker) {
103 NOTREACHED() << "Invalid buffer_id."; 166 NOTREACHED() << "Invalid buffer_id.";
104 return; 167 return;
105 } 168 }
106 DCHECK_GE(buffer->consumer_hold_count, num_clients); 169 DCHECK_GE(tracker->consumer_hold_count(), num_clients);
107 170
108 buffer->consumer_hold_count -= num_clients; 171 tracker->set_consumer_hold_count(tracker->consumer_hold_count() -
172 num_clients);
109 } 173 }
110 174
111 VideoCaptureBufferPool::Buffer::Buffer() 175 int VideoCaptureBufferPool::ReserveForProducerInternal(
112 : held_by_producer(false), consumer_hold_count(0) {} 176 media::VideoPixelFormat format,
177 const gfx::Size& dimensions,
178 int* buffer_id_to_drop) {
179 DCHECK(format == media::PIXEL_FORMAT_I420 ||
180 format == media::PIXEL_FORMAT_ARGB ||
181 format == media::PIXEL_FORMAT_TEXTURE);
182 lock_.AssertAcquired();
183 const media::VideoFrame::Format frame_format =
184 VideoPixelFormatToVideoFrameFormat(format);
185 const size_t size_in_bytes =
186 VideoFrame::AllocationSize(frame_format, dimensions);
113 187
114 int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size, 188 // Look for a tracker that's allocated, big enough, and not in use. Track the
115 int* buffer_id_to_drop) { 189 // largest one that's not big enough, in case we have to reallocate a tracker.
116 lock_.AssertAcquired();
117
118 // 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.
120 *buffer_id_to_drop = kInvalidId; 190 *buffer_id_to_drop = kInvalidId;
121 size_t realloc_size = 0; 191 size_t realloc_size = 0;
122 BufferMap::iterator realloc = buffers_.end(); 192 TrackerMap::iterator tracker_to_drop = trackers_.end();
123 for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); ++it) { 193 for (TrackerMap::iterator it = trackers_.begin(); it != trackers_.end();
124 Buffer* buffer = it->second; 194 ++it) {
125 if (!buffer->consumer_hold_count && !buffer->held_by_producer) { 195 Tracker* const tracker = it->second;
126 if (buffer->shared_memory.requested_size() >= size) { 196 if (!tracker->consumer_hold_count() && !tracker->held_by_producer()) {
127 // Existing buffer is big enough. Reuse it. 197 if (tracker->requested_size() >= size_in_bytes) {
128 buffer->held_by_producer = true; 198 // Existing tracker is big enough. Reuse it.
199 tracker->set_held_by_producer(true);
129 return it->first; 200 return it->first;
130 } 201 }
131 if (buffer->shared_memory.requested_size() > realloc_size) { 202 if (tracker->requested_size() > realloc_size) {
132 realloc_size = buffer->shared_memory.requested_size(); 203 realloc_size = tracker->requested_size();
133 realloc = it; 204 tracker_to_drop = it;
134 } 205 }
135 } 206 }
136 } 207 }
137 208
138 // Preferentially grow the pool by creating a new buffer. If we're at maximum 209 // Preferably grow the pool by creating a new tracker. If we're at maximum
139 // size, then reallocate by deleting an existing one instead. 210 // size, then reallocate by deleting an existing one instead.
140 if (buffers_.size() == static_cast<size_t>(count_)) { 211 if (trackers_.size() == static_cast<size_t>(count_)) {
141 if (realloc == buffers_.end()) { 212 if (tracker_to_drop == trackers_.end()) {
142 // We're out of space, and can't find an unused buffer to reallocate. 213 // We're out of space, and can't find an unused tracker to reallocate.
143 return kInvalidId; 214 return kInvalidId;
144 } 215 }
145 *buffer_id_to_drop = realloc->first; 216 *buffer_id_to_drop = tracker_to_drop->first;
146 delete realloc->second; 217 delete tracker_to_drop->second;
147 buffers_.erase(realloc); 218 trackers_.erase(tracker_to_drop);
148 } 219 }
149 220
150 // Create the new buffer. 221 // Create the new tracker.
151 int buffer_id = next_buffer_id_++; 222 const int buffer_id = next_buffer_id_++;
152 scoped_ptr<Buffer> buffer(new Buffer()); 223 scoped_ptr<Tracker> tracker = Tracker::CreateTracker();
153 if (size) { 224 if (!tracker->Init(frame_format, dimensions))
154 // |size| can be 0 for buffers that do not require memory backing. 225 return kInvalidId;
155 if (!buffer->shared_memory.CreateAndMapAnonymous(size)) 226 tracker->set_held_by_producer(true);
156 return kInvalidId; 227 trackers_[buffer_id] = tracker.release();
157 } 228
158 buffer->held_by_producer = true;
159 buffers_[buffer_id] = buffer.release();
160 return buffer_id; 229 return buffer_id;
161 } 230 }
162 231
163 VideoCaptureBufferPool::Buffer* VideoCaptureBufferPool::GetBuffer( 232 VideoCaptureBufferPool::Tracker* VideoCaptureBufferPool::GetTracker(
164 int buffer_id) { 233 int buffer_id) {
165 BufferMap::iterator it = buffers_.find(buffer_id); 234 TrackerMap::const_iterator it = trackers_.find(buffer_id);
166 if (it == buffers_.end()) 235 return (it == trackers_.end()) ? NULL : it->second;
167 return NULL;
168 return it->second;
169 } 236 }
170 237
171 } // namespace content 238 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698