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

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

Issue 2607203002: [Mojo Video Capture] Retire buffers when Android Chromium goes to the background (Closed)
Patch Set: mcasas comments Created 3 years, 10 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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_controller.h" 5 #include "content/browser/renderer_host/media/video_capture_controller.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <map> 10 #include <map>
(...skipping 24 matching lines...) Expand all
35 using media::VideoFrame; 35 using media::VideoFrame;
36 using media::VideoFrameMetadata; 36 using media::VideoFrameMetadata;
37 37
38 namespace content { 38 namespace content {
39 39
40 namespace { 40 namespace {
41 41
42 static const int kInfiniteRatio = 99999; 42 static const int kInfiniteRatio = 99999;
43 43
44 #define UMA_HISTOGRAM_ASPECT_RATIO(name, width, height) \ 44 #define UMA_HISTOGRAM_ASPECT_RATIO(name, width, height) \
45 UMA_HISTOGRAM_SPARSE_SLOWLY( \ 45 UMA_HISTOGRAM_SPARSE_SLOWLY( \
46 name, \ 46 name, (height) ? ((width)*100) / (height) : kInfiniteRatio);
47 (height) ? ((width) * 100) / (height) : kInfiniteRatio);
48 47
49 } // anonymous namespace 48 } // anonymous namespace
50 49
51 struct VideoCaptureController::ControllerClient { 50 struct VideoCaptureController::ControllerClient {
52 ControllerClient(VideoCaptureControllerID id, 51 ControllerClient(VideoCaptureControllerID id,
53 VideoCaptureControllerEventHandler* handler, 52 VideoCaptureControllerEventHandler* handler,
54 media::VideoCaptureSessionId session_id, 53 media::VideoCaptureSessionId session_id,
55 const media::VideoCaptureParams& params) 54 const media::VideoCaptureParams& params)
56 : controller_id(id), 55 : controller_id(id),
57 event_handler(handler), 56 event_handler(handler),
58 session_id(session_id), 57 session_id(session_id),
59 parameters(params), 58 parameters(params),
60 session_closed(false), 59 session_closed(false),
61 paused(false) {} 60 paused(false) {}
62 61
63 ~ControllerClient() {} 62 ~ControllerClient() {}
64 63
65 // ID used for identifying this object. 64 // ID used for identifying this object.
66 const VideoCaptureControllerID controller_id; 65 const VideoCaptureControllerID controller_id;
67 VideoCaptureControllerEventHandler* const event_handler; 66 VideoCaptureControllerEventHandler* const event_handler;
68 67
69 const media::VideoCaptureSessionId session_id; 68 const media::VideoCaptureSessionId session_id;
70 const media::VideoCaptureParams parameters; 69 const media::VideoCaptureParams parameters;
71 70
72 // Buffers that are currently known to this client. 71 std::vector<int> known_buffer_context_ids;
73 std::vector<int> known_buffers; 72 // |buffer_context_id|s of buffers currently being consumed by this client.
74
75 // Buffers currently held by this client.
76 std::vector<int> buffers_in_use; 73 std::vector<int> buffers_in_use;
77 74
78 // State of capture session, controlled by VideoCaptureManager directly. This 75 // State of capture session, controlled by VideoCaptureManager directly. This
79 // transitions to true as soon as StopSession() occurs, at which point the 76 // transitions to true as soon as StopSession() occurs, at which point the
80 // client is sent an OnEnded() event. However, because the client retains a 77 // client is sent an OnEnded() event. However, because the client retains a
81 // VideoCaptureController* pointer, its ControllerClient entry lives on until 78 // VideoCaptureController* pointer, its ControllerClient entry lives on until
82 // it unregisters itself via RemoveClient(), which may happen asynchronously. 79 // it unregisters itself via RemoveClient(), which may happen asynchronously.
83 // 80 //
84 // TODO(nick): If we changed the semantics of VideoCaptureHost so that 81 // TODO(nick): If we changed the semantics of VideoCaptureHost so that
85 // OnEnded() events were processed synchronously (with the RemoveClient() done 82 // OnEnded() events were processed synchronously (with the RemoveClient() done
86 // implicitly), we could avoid tracking this state here in the Controller, and 83 // implicitly), we could avoid tracking this state here in the Controller, and
87 // simplify the code in both places. 84 // simplify the code in both places.
88 bool session_closed; 85 bool session_closed;
89 86
90 // Indicates whether the client is paused, if true, VideoCaptureController 87 // Indicates whether the client is paused, if true, VideoCaptureController
91 // stops updating its buffer. 88 // stops updating its buffer.
92 bool paused; 89 bool paused;
93 }; 90 };
94 91
95 VideoCaptureController::BufferState::BufferState( 92 VideoCaptureController::BufferContext::BufferContext(
93 int buffer_context_id,
96 int buffer_id, 94 int buffer_id,
97 int frame_feedback_id,
98 media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer, 95 media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer,
99 media::FrameBufferPool* frame_buffer_pool) 96 media::FrameBufferPool* frame_buffer_pool)
100 : buffer_id_(buffer_id), 97 : buffer_context_id_(buffer_context_id),
101 frame_feedback_id_(frame_feedback_id), 98 buffer_id_(buffer_id),
99 is_retired_(false),
100 frame_feedback_id_(0),
102 consumer_feedback_observer_(consumer_feedback_observer), 101 consumer_feedback_observer_(consumer_feedback_observer),
103 frame_buffer_pool_(frame_buffer_pool), 102 frame_buffer_pool_(frame_buffer_pool),
104 max_consumer_utilization_( 103 max_consumer_utilization_(
105 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded), 104 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded),
106 consumer_hold_count_(0) {} 105 consumer_hold_count_(0) {}
107 106
108 VideoCaptureController::BufferState::~BufferState() = default; 107 VideoCaptureController::BufferContext::~BufferContext() = default;
109 108
110 VideoCaptureController::BufferState::BufferState( 109 VideoCaptureController::BufferContext::BufferContext(
111 const VideoCaptureController::BufferState& other) = default; 110 const VideoCaptureController::BufferContext& other) = default;
112 111
113 void VideoCaptureController::BufferState::RecordConsumerUtilization( 112 VideoCaptureController::BufferContext& VideoCaptureController::BufferContext::
113 operator=(const BufferContext& other) = default;
114
115 void VideoCaptureController::BufferContext::RecordConsumerUtilization(
114 double utilization) { 116 double utilization) {
115 if (std::isfinite(utilization) && utilization >= 0.0) { 117 if (std::isfinite(utilization) && utilization >= 0.0) {
116 max_consumer_utilization_ = 118 max_consumer_utilization_ =
117 std::max(max_consumer_utilization_, utilization); 119 std::max(max_consumer_utilization_, utilization);
118 } 120 }
119 } 121 }
120 122
121 void VideoCaptureController::BufferState::IncreaseConsumerCount() { 123 void VideoCaptureController::BufferContext::IncreaseConsumerCount() {
122 if (consumer_hold_count_ == 0) 124 if (consumer_hold_count_ == 0)
123 if (frame_buffer_pool_ != nullptr) 125 if (frame_buffer_pool_ != nullptr)
124 frame_buffer_pool_->SetBufferHold(buffer_id_); 126 frame_buffer_pool_->SetBufferHold(buffer_id_);
125 consumer_hold_count_++; 127 consumer_hold_count_++;
126 } 128 }
127 129
128 void VideoCaptureController::BufferState::DecreaseConsumerCount() { 130 void VideoCaptureController::BufferContext::DecreaseConsumerCount() {
129 consumer_hold_count_--; 131 consumer_hold_count_--;
130 if (consumer_hold_count_ == 0) { 132 if (consumer_hold_count_ == 0) {
131 if (consumer_feedback_observer_ != nullptr && 133 if (consumer_feedback_observer_ != nullptr &&
132 max_consumer_utilization_ != 134 max_consumer_utilization_ !=
133 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded) { 135 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded) {
134 consumer_feedback_observer_->OnUtilizationReport( 136 consumer_feedback_observer_->OnUtilizationReport(
135 frame_feedback_id_, max_consumer_utilization_); 137 frame_feedback_id_, max_consumer_utilization_);
136 } 138 }
137 if (frame_buffer_pool_ != nullptr) 139 if (frame_buffer_pool_ != nullptr)
138 frame_buffer_pool_->ReleaseBufferHold(buffer_id_); 140 frame_buffer_pool_->ReleaseBufferHold(buffer_id_);
139 max_consumer_utilization_ = 141 max_consumer_utilization_ =
140 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded; 142 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded;
141 } 143 }
142 } 144 }
143 145
144 bool VideoCaptureController::BufferState::HasZeroConsumerHoldCount() { 146 bool VideoCaptureController::BufferContext::HasZeroConsumerHoldCount() {
145 return consumer_hold_count_ == 0; 147 return consumer_hold_count_ == 0;
146 } 148 }
147 149
148 void VideoCaptureController::BufferState::SetFrameFeedbackId(int id) {
149 DCHECK_CURRENTLY_ON(BrowserThread::IO);
150 frame_feedback_id_ = id;
151 }
152
153 void VideoCaptureController::BufferState::SetConsumerFeedbackObserver(
154 media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer) {
155 DCHECK_CURRENTLY_ON(BrowserThread::IO);
156 consumer_feedback_observer_ = consumer_feedback_observer;
157 }
158
159 void VideoCaptureController::BufferState::SetFrameBufferPool(
160 media::FrameBufferPool* frame_buffer_pool) {
161 DCHECK_CURRENTLY_ON(BrowserThread::IO);
162 frame_buffer_pool_ = frame_buffer_pool;
163 }
164
165 VideoCaptureController::VideoCaptureController() 150 VideoCaptureController::VideoCaptureController()
166 : frame_buffer_pool_(nullptr), 151 : frame_buffer_pool_(nullptr),
167 consumer_feedback_observer_(nullptr), 152 consumer_feedback_observer_(nullptr),
168 state_(VIDEO_CAPTURE_STATE_STARTED), 153 state_(VIDEO_CAPTURE_STATE_STARTED),
169 has_received_frames_(false), 154 has_received_frames_(false),
170 weak_ptr_factory_(this) { 155 weak_ptr_factory_(this) {
171 DCHECK_CURRENTLY_ON(BrowserThread::IO); 156 DCHECK_CURRENTLY_ON(BrowserThread::IO);
172 } 157 }
173 158
174 VideoCaptureController::~VideoCaptureController() = default; 159 VideoCaptureController::~VideoCaptureController() = default;
175 160
176 base::WeakPtr<VideoCaptureController> 161 base::WeakPtr<VideoCaptureController>
177 VideoCaptureController::GetWeakPtrForIOThread() { 162 VideoCaptureController::GetWeakPtrForIOThread() {
178 return weak_ptr_factory_.GetWeakPtr(); 163 return weak_ptr_factory_.GetWeakPtr();
179 } 164 }
180 165
181 void VideoCaptureController::SetFrameBufferPool( 166 void VideoCaptureController::SetFrameBufferPool(
182 std::unique_ptr<media::FrameBufferPool> frame_buffer_pool) { 167 std::unique_ptr<media::FrameBufferPool> frame_buffer_pool) {
183 DCHECK_CURRENTLY_ON(BrowserThread::IO); 168 DCHECK_CURRENTLY_ON(BrowserThread::IO);
184 frame_buffer_pool_ = std::move(frame_buffer_pool); 169 frame_buffer_pool_ = std::move(frame_buffer_pool);
185 // Update existing BufferState entries. 170 // Update existing BufferContext entries.
186 for (auto& entry : buffer_id_to_state_map_) 171 for (auto& entry : buffer_contexts_)
187 entry.second.SetFrameBufferPool(frame_buffer_pool_.get()); 172 entry.set_frame_buffer_pool(frame_buffer_pool_.get());
188 } 173 }
189 174
190 void VideoCaptureController::SetConsumerFeedbackObserver( 175 void VideoCaptureController::SetConsumerFeedbackObserver(
191 std::unique_ptr<media::VideoFrameConsumerFeedbackObserver> 176 std::unique_ptr<media::VideoFrameConsumerFeedbackObserver>
192 consumer_feedback_observer) { 177 consumer_feedback_observer) {
193 DCHECK_CURRENTLY_ON(BrowserThread::IO); 178 DCHECK_CURRENTLY_ON(BrowserThread::IO);
194 consumer_feedback_observer_ = std::move(consumer_feedback_observer); 179 consumer_feedback_observer_ = std::move(consumer_feedback_observer);
195 // Update existing BufferState entries. 180 // Update existing BufferContext entries.
196 for (auto& entry : buffer_id_to_state_map_) 181 for (auto& entry : buffer_contexts_)
197 entry.second.SetConsumerFeedbackObserver(consumer_feedback_observer_.get()); 182 entry.set_consumer_feedback_observer(consumer_feedback_observer_.get());
198 } 183 }
199 184
200 void VideoCaptureController::AddClient( 185 void VideoCaptureController::AddClient(
201 VideoCaptureControllerID id, 186 VideoCaptureControllerID id,
202 VideoCaptureControllerEventHandler* event_handler, 187 VideoCaptureControllerEventHandler* event_handler,
203 media::VideoCaptureSessionId session_id, 188 media::VideoCaptureSessionId session_id,
204 const media::VideoCaptureParams& params) { 189 const media::VideoCaptureParams& params) {
205 DCHECK_CURRENTLY_ON(BrowserThread::IO); 190 DCHECK_CURRENTLY_ON(BrowserThread::IO);
206 DVLOG(1) << "VideoCaptureController::AddClient() -- id=" << id 191 DVLOG(1) << "VideoCaptureController::AddClient() -- id=" << id
207 << ", session_id=" << session_id 192 << ", session_id=" << session_id << ", params.requested_format="
208 << ", params.requested_format="
209 << media::VideoCaptureFormat::ToString(params.requested_format); 193 << media::VideoCaptureFormat::ToString(params.requested_format);
210 194
211 // Check that requested VideoCaptureParams are valid and supported. If not, 195 // Check that requested VideoCaptureParams are valid and supported. If not,
212 // report an error immediately and punt. 196 // report an error immediately and punt.
213 if (!params.IsValid() || 197 if (!params.IsValid() ||
214 !(params.requested_format.pixel_format == media::PIXEL_FORMAT_I420 || 198 !(params.requested_format.pixel_format == media::PIXEL_FORMAT_I420 ||
215 params.requested_format.pixel_format == media::PIXEL_FORMAT_Y16) || 199 params.requested_format.pixel_format == media::PIXEL_FORMAT_Y16) ||
216 params.requested_format.pixel_storage != media::PIXEL_STORAGE_CPU) { 200 params.requested_format.pixel_storage != media::PIXEL_STORAGE_CPU) {
217 // Crash in debug builds since the renderer should not have asked for 201 // Crash in debug builds since the renderer should not have asked for
218 // invalid or unsupported parameters. 202 // invalid or unsupported parameters.
(...skipping 30 matching lines...) Expand all
249 int VideoCaptureController::RemoveClient( 233 int VideoCaptureController::RemoveClient(
250 VideoCaptureControllerID id, 234 VideoCaptureControllerID id,
251 VideoCaptureControllerEventHandler* event_handler) { 235 VideoCaptureControllerEventHandler* event_handler) {
252 DCHECK_CURRENTLY_ON(BrowserThread::IO); 236 DCHECK_CURRENTLY_ON(BrowserThread::IO);
253 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id; 237 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id;
254 238
255 ControllerClient* client = FindClient(id, event_handler, controller_clients_); 239 ControllerClient* client = FindClient(id, event_handler, controller_clients_);
256 if (!client) 240 if (!client)
257 return kInvalidMediaCaptureSessionId; 241 return kInvalidMediaCaptureSessionId;
258 242
259 // Take back all buffers held by the |client|. 243 for (const auto& buffer_id : client->buffers_in_use) {
260 for (const auto& buffer_id : client->buffers_in_use) 244 OnClientFinishedConsumingBuffer(
261 buffer_id_to_state_map_.at(buffer_id).DecreaseConsumerCount(); 245 client, buffer_id,
246 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded);
247 }
262 client->buffers_in_use.clear(); 248 client->buffers_in_use.clear();
263 249
264 int session_id = client->session_id; 250 int session_id = client->session_id;
265 controller_clients_.remove_if( 251 controller_clients_.remove_if(
266 [client](const std::unique_ptr<ControllerClient>& ptr) { 252 [client](const std::unique_ptr<ControllerClient>& ptr) {
267 return ptr.get() == client; 253 return ptr.get() == client;
268 }); 254 });
269 255
270 return session_id; 256 return session_id;
271 } 257 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 NOTREACHED(); 340 NOTREACHED();
355 return; 341 return;
356 } 342 }
357 auto buffers_in_use_entry_iter = 343 auto buffers_in_use_entry_iter =
358 std::find(std::begin(client->buffers_in_use), 344 std::find(std::begin(client->buffers_in_use),
359 std::end(client->buffers_in_use), buffer_id); 345 std::end(client->buffers_in_use), buffer_id);
360 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use)) { 346 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use)) {
361 NOTREACHED(); 347 NOTREACHED();
362 return; 348 return;
363 } 349 }
350 client->buffers_in_use.erase(buffers_in_use_entry_iter);
364 351
365 BufferState& buffer_state = buffer_id_to_state_map_.at(buffer_id); 352 OnClientFinishedConsumingBuffer(client, buffer_id,
366 buffer_state.RecordConsumerUtilization(consumer_resource_utilization); 353 consumer_resource_utilization);
367 buffer_state.DecreaseConsumerCount();
368 client->buffers_in_use.erase(buffers_in_use_entry_iter);
369 } 354 }
370 355
371 const media::VideoCaptureFormat& 356 const media::VideoCaptureFormat& VideoCaptureController::GetVideoCaptureFormat()
372 VideoCaptureController::GetVideoCaptureFormat() const { 357 const {
373 DCHECK_CURRENTLY_ON(BrowserThread::IO); 358 DCHECK_CURRENTLY_ON(BrowserThread::IO);
374 return video_capture_format_; 359 return video_capture_format_;
375 } 360 }
376 361
377 void VideoCaptureController::OnIncomingCapturedVideoFrame( 362 void VideoCaptureController::OnIncomingCapturedVideoFrame(
378 media::VideoCaptureDevice::Client::Buffer buffer, 363 media::VideoCaptureDevice::Client::Buffer buffer,
379 scoped_refptr<VideoFrame> frame) { 364 scoped_refptr<VideoFrame> frame) {
380 DCHECK_CURRENTLY_ON(BrowserThread::IO); 365 DCHECK_CURRENTLY_ON(BrowserThread::IO);
381 const int buffer_id = buffer.id(); 366 const int buffer_id_from_producer = buffer.id();
382 DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId); 367 DCHECK_NE(buffer_id_from_producer, media::VideoCaptureBufferPool::kInvalidId);
383 368 auto buffer_context_iter =
384 // Insert if not exists. 369 FindUnretiredBufferContextFromBufferId(buffer_id_from_producer);
385 const auto insert_result = buffer_id_to_state_map_.insert(std::make_pair( 370 if (buffer_context_iter == buffer_contexts_.end()) {
386 buffer_id, BufferState(buffer_id, buffer.frame_feedback_id(), 371 // A new buffer has been shared with us. Create new BufferContext.
387 consumer_feedback_observer_.get(), 372 buffer_contexts_.emplace_back(
388 frame_buffer_pool_.get()))); 373 next_buffer_context_id_++, buffer_id_from_producer,
389 BufferState& buffer_state = insert_result.first->second; 374 consumer_feedback_observer_.get(), frame_buffer_pool_.get());
390 DCHECK(buffer_state.HasZeroConsumerHoldCount()); 375 buffer_context_iter = buffer_contexts_.end() - 1;
391 // If a BufferState for |buffer_id| already existed, we must update the 376 }
392 // |frame_feedback_id| of the existing entry. 377 buffer_context_iter->set_frame_feedback_id(buffer.frame_feedback_id());
393 if (!insert_result.second) 378 DCHECK(buffer_context_iter->HasZeroConsumerHoldCount());
394 buffer_state.SetFrameFeedbackId(buffer.frame_feedback_id());
395 379
396 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 380 if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
397 if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) { 381 if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) {
398 frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE, 382 frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE,
399 video_capture_format_.frame_rate); 383 video_capture_format_.frame_rate);
400 } 384 }
401 std::unique_ptr<base::DictionaryValue> metadata = 385 std::unique_ptr<base::DictionaryValue> metadata =
402 frame->metadata()->CopyInternalValues(); 386 frame->metadata()->CopyInternalValues();
403 387
404 // Only I420 and Y16 pixel formats are currently supported. 388 // Only I420 and Y16 pixel formats are currently supported.
405 DCHECK(frame->format() == media::PIXEL_FORMAT_I420 || 389 DCHECK(frame->format() == media::PIXEL_FORMAT_I420 ||
406 frame->format() == media::PIXEL_FORMAT_Y16) 390 frame->format() == media::PIXEL_FORMAT_Y16)
407 << "Unsupported pixel format: " 391 << "Unsupported pixel format: "
408 << media::VideoPixelFormatToString(frame->format()); 392 << media::VideoPixelFormatToString(frame->format());
409 393
410 // Sanity-checks to confirm |frame| is actually being backed by |buffer|. 394 // Sanity-checks to confirm |frame| is actually being backed by |buffer|.
411 auto buffer_access = 395 auto buffer_access =
412 buffer.handle_provider()->GetHandleForInProcessAccess(); 396 buffer.handle_provider()->GetHandleForInProcessAccess();
413 DCHECK(frame->storage_type() == media::VideoFrame::STORAGE_SHMEM); 397 DCHECK(frame->storage_type() == media::VideoFrame::STORAGE_SHMEM);
414 DCHECK(frame->data(media::VideoFrame::kYPlane) >= buffer_access->data() && 398 DCHECK(frame->data(media::VideoFrame::kYPlane) >= buffer_access->data() &&
415 (frame->data(media::VideoFrame::kYPlane) < 399 (frame->data(media::VideoFrame::kYPlane) <
416 (buffer_access->data() + buffer_access->mapped_size()))) 400 (buffer_access->data() + buffer_access->mapped_size())))
417 << "VideoFrame does not appear to be backed by Buffer"; 401 << "VideoFrame does not appear to be backed by Buffer";
418 402
403 const int buffer_context_id = buffer_context_iter->buffer_context_id();
419 for (const auto& client : controller_clients_) { 404 for (const auto& client : controller_clients_) {
420 if (client->session_closed || client->paused) 405 if (client->session_closed || client->paused)
421 continue; 406 continue;
422 407
423 // On the first use of a buffer on a client, share the memory handles. 408 // On the first use of a BufferContext on a client, share the memory
424 auto known_buffers_entry_iter = 409 // handles.
425 std::find(std::begin(client->known_buffers), 410 auto known_buffers_entry_iter = std::find(
426 std::end(client->known_buffers), buffer_id); 411 std::begin(client->known_buffer_context_ids),
412 std::end(client->known_buffer_context_ids), buffer_context_id);
427 bool is_new_buffer = false; 413 bool is_new_buffer = false;
428 if (known_buffers_entry_iter == std::end(client->known_buffers)) { 414 if (known_buffers_entry_iter ==
429 client->known_buffers.push_back(buffer_id); 415 std::end(client->known_buffer_context_ids)) {
416 client->known_buffer_context_ids.push_back(buffer_context_id);
430 is_new_buffer = true; 417 is_new_buffer = true;
431 } 418 }
432 if (is_new_buffer) { 419 if (is_new_buffer) {
433 mojo::ScopedSharedBufferHandle handle = 420 mojo::ScopedSharedBufferHandle handle =
434 buffer.handle_provider()->GetHandleForInterProcessTransit(); 421 buffer.handle_provider()->GetHandleForInterProcessTransit();
435 client->event_handler->OnBufferCreated( 422 client->event_handler->OnBufferCreated(
436 client->controller_id, std::move(handle), 423 client->controller_id, std::move(handle),
437 buffer_access->mapped_size(), buffer_id); 424 buffer_access->mapped_size(), buffer_context_id);
438 } 425 }
439 client->event_handler->OnBufferReady(client->controller_id, buffer_id, 426 client->event_handler->OnBufferReady(client->controller_id,
440 frame); 427 buffer_context_id, frame);
441 428
442 auto buffers_in_use_entry_iter = 429 auto buffers_in_use_entry_iter =
443 std::find(std::begin(client->buffers_in_use), 430 std::find(std::begin(client->buffers_in_use),
444 std::end(client->buffers_in_use), buffer_id); 431 std::end(client->buffers_in_use), buffer_context_id);
445 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use)) 432 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use))
446 client->buffers_in_use.push_back(buffer_id); 433 client->buffers_in_use.push_back(buffer_context_id);
447 else 434 else
448 DCHECK(false) << "Unexpected duplicate buffer: " << buffer_id; 435 DCHECK(false) << "Unexpected duplicate buffer: " << buffer_context_id;
449 buffer_state.IncreaseConsumerCount(); 436 buffer_context_iter->IncreaseConsumerCount();
450 } 437 }
451 } 438 }
452 439
453 if (!has_received_frames_) { 440 if (!has_received_frames_) {
454 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width", 441 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width",
455 frame->visible_rect().width()); 442 frame->visible_rect().width());
456 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height", 443 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height",
457 frame->visible_rect().height()); 444 frame->visible_rect().height());
458 UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio", 445 UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio",
459 frame->visible_rect().width(), 446 frame->visible_rect().width(),
460 frame->visible_rect().height()); 447 frame->visible_rect().height());
461 double frame_rate = 0.0f; 448 double frame_rate = 0.0f;
462 if (!frame->metadata()->GetDouble(VideoFrameMetadata::FRAME_RATE, 449 if (!frame->metadata()->GetDouble(VideoFrameMetadata::FRAME_RATE,
463 &frame_rate)) { 450 &frame_rate)) {
464 frame_rate = video_capture_format_.frame_rate; 451 frame_rate = video_capture_format_.frame_rate;
465 } 452 }
466 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", frame_rate); 453 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", frame_rate);
467 has_received_frames_ = true; 454 has_received_frames_ = true;
468 } 455 }
469 } 456 }
470 457
471 void VideoCaptureController::OnError() { 458 void VideoCaptureController::OnError() {
472 DCHECK_CURRENTLY_ON(BrowserThread::IO); 459 DCHECK_CURRENTLY_ON(BrowserThread::IO);
473 state_ = VIDEO_CAPTURE_STATE_ERROR; 460 state_ = VIDEO_CAPTURE_STATE_ERROR;
474 461
475 for (const auto& client : controller_clients_) { 462 for (const auto& client : controller_clients_) {
476 if (client->session_closed) 463 if (client->session_closed)
477 continue; 464 continue;
478 client->event_handler->OnError(client->controller_id); 465 client->event_handler->OnError(client->controller_id);
479 } 466 }
480 } 467 }
481 468
482 void VideoCaptureController::OnLog(const std::string& message) { 469 void VideoCaptureController::OnLog(const std::string& message) {
483 DCHECK_CURRENTLY_ON(BrowserThread::IO); 470 DCHECK_CURRENTLY_ON(BrowserThread::IO);
484 MediaStreamManager::SendMessageToNativeLog("Video capture: " + message); 471 MediaStreamManager::SendMessageToNativeLog("Video capture: " + message);
485 } 472 }
486 473
487 void VideoCaptureController::OnBufferDestroyed(int buffer_id_to_drop) { 474 void VideoCaptureController::OnBufferRetired(int buffer_id) {
488 DCHECK_CURRENTLY_ON(BrowserThread::IO); 475 DCHECK_CURRENTLY_ON(BrowserThread::IO);
489 476
490 for (const auto& client : controller_clients_) { 477 auto buffer_context_iter = FindUnretiredBufferContextFromBufferId(buffer_id);
491 if (client->session_closed) 478 DCHECK(buffer_context_iter != buffer_contexts_.end());
492 continue;
493 479
494 auto known_buffers_entry_iter = 480 // If there are any clients still using the buffer, we need to allow them
495 std::find(std::begin(client->known_buffers), 481 // to finish up. We need to hold on to the BufferContext entry until then,
496 std::end(client->known_buffers), buffer_id_to_drop); 482 // because it contains the consumer hold.
497 if (known_buffers_entry_iter != std::end(client->known_buffers)) { 483 if (buffer_context_iter->HasZeroConsumerHoldCount())
498 client->known_buffers.erase(known_buffers_entry_iter); 484 ReleaseBufferContext(buffer_context_iter);
499 client->event_handler->OnBufferDestroyed(client->controller_id, 485 else
500 buffer_id_to_drop); 486 buffer_context_iter->set_is_retired();
501 }
502 }
503
504 buffer_id_to_state_map_.erase(buffer_id_to_drop);
505 } 487 }
506 488
507 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( 489 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient(
508 VideoCaptureControllerID id, 490 VideoCaptureControllerID id,
509 VideoCaptureControllerEventHandler* handler, 491 VideoCaptureControllerEventHandler* handler,
510 const ControllerClients& clients) { 492 const ControllerClients& clients) {
511 for (const auto& client : clients) { 493 for (const auto& client : clients) {
512 if (client->controller_id == id && client->event_handler == handler) 494 if (client->controller_id == id && client->event_handler == handler)
513 return client.get(); 495 return client.get();
514 } 496 }
515 return nullptr; 497 return nullptr;
516 } 498 }
517 499
518 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( 500 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient(
519 int session_id, 501 int session_id,
520 const ControllerClients& clients) { 502 const ControllerClients& clients) {
521 for (const auto& client : clients) { 503 for (const auto& client : clients) {
522 if (client->session_id == session_id) 504 if (client->session_id == session_id)
523 return client.get(); 505 return client.get();
524 } 506 }
525 return nullptr; 507 return nullptr;
526 } 508 }
527 509
510 std::vector<VideoCaptureController::BufferContext>::iterator
511 VideoCaptureController::FindBufferContextFromBufferContextId(
512 int buffer_context_id) {
513 return std::find_if(buffer_contexts_.begin(), buffer_contexts_.end(),
514 [buffer_context_id](const BufferContext& entry) {
515 return entry.buffer_context_id() == buffer_context_id;
516 });
517 }
518
519 std::vector<VideoCaptureController::BufferContext>::iterator
520 VideoCaptureController::FindUnretiredBufferContextFromBufferId(int buffer_id) {
521 return std::find_if(buffer_contexts_.begin(), buffer_contexts_.end(),
522 [buffer_id](const BufferContext& entry) {
523 return (entry.buffer_id() == buffer_id) &&
524 (entry.is_retired() == false);
525 });
526 }
527
528 void VideoCaptureController::OnClientFinishedConsumingBuffer(
529 ControllerClient* client,
530 int buffer_context_id,
531 double consumer_resource_utilization) {
532 auto buffer_context_iter =
533 FindBufferContextFromBufferContextId(buffer_context_id);
534 DCHECK(buffer_context_iter != buffer_contexts_.end());
535
536 buffer_context_iter->RecordConsumerUtilization(consumer_resource_utilization);
537 buffer_context_iter->DecreaseConsumerCount();
538 if (buffer_context_iter->HasZeroConsumerHoldCount() &&
539 buffer_context_iter->is_retired()) {
540 ReleaseBufferContext(buffer_context_iter);
541 }
542 }
543
544 void VideoCaptureController::ReleaseBufferContext(
545 const std::vector<BufferContext>::iterator& buffer_context_iter) {
546 for (const auto& client : controller_clients_) {
547 if (client->session_closed)
548 continue;
549 auto entry_iter = std::find(std::begin(client->known_buffer_context_ids),
550 std::end(client->known_buffer_context_ids),
551 buffer_context_iter->buffer_context_id());
552 if (entry_iter != std::end(client->known_buffer_context_ids)) {
553 client->known_buffer_context_ids.erase(entry_iter);
554 client->event_handler->OnBufferDestroyed(
555 client->controller_id, buffer_context_iter->buffer_context_id());
556 }
557 }
558 buffer_contexts_.erase(buffer_context_iter);
559 }
560
528 } // namespace content 561 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698