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

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: Support reused buffer ids in Controller 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),
102 consumer_feedback_observer_(consumer_feedback_observer), 99 consumer_feedback_observer_(consumer_feedback_observer),
103 frame_buffer_pool_(frame_buffer_pool), 100 frame_buffer_pool_(frame_buffer_pool),
104 max_consumer_utilization_( 101 max_consumer_utilization_(
105 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded), 102 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded),
106 consumer_hold_count_(0) {} 103 consumer_hold_count_(0) {}
107 104
108 VideoCaptureController::BufferState::~BufferState() = default; 105 VideoCaptureController::BufferContext::~BufferContext() = default;
109 106
110 VideoCaptureController::BufferState::BufferState( 107 VideoCaptureController::BufferContext::BufferContext(
111 const VideoCaptureController::BufferState& other) = default; 108 const VideoCaptureController::BufferContext& other) = default;
112 109
113 void VideoCaptureController::BufferState::RecordConsumerUtilization( 110 VideoCaptureController::BufferContext& VideoCaptureController::BufferContext::
111 operator=(const BufferContext& other) = default;
112
113 void VideoCaptureController::BufferContext::RecordConsumerUtilization(
114 double utilization) { 114 double utilization) {
115 if (std::isfinite(utilization) && utilization >= 0.0) { 115 if (std::isfinite(utilization) && utilization >= 0.0) {
116 max_consumer_utilization_ = 116 max_consumer_utilization_ =
117 std::max(max_consumer_utilization_, utilization); 117 std::max(max_consumer_utilization_, utilization);
118 } 118 }
119 } 119 }
120 120
121 void VideoCaptureController::BufferState::IncreaseConsumerCount() { 121 void VideoCaptureController::BufferContext::IncreaseConsumerCount() {
122 if (consumer_hold_count_ == 0) 122 if (consumer_hold_count_ == 0)
123 if (frame_buffer_pool_ != nullptr) 123 if (frame_buffer_pool_ != nullptr)
124 frame_buffer_pool_->SetBufferHold(buffer_id_); 124 frame_buffer_pool_->SetBufferHold(buffer_id_);
125 consumer_hold_count_++; 125 consumer_hold_count_++;
126 } 126 }
127 127
128 void VideoCaptureController::BufferState::DecreaseConsumerCount() { 128 void VideoCaptureController::BufferContext::DecreaseConsumerCount() {
129 consumer_hold_count_--; 129 consumer_hold_count_--;
130 if (consumer_hold_count_ == 0) { 130 if (consumer_hold_count_ == 0) {
131 if (consumer_feedback_observer_ != nullptr && 131 if (consumer_feedback_observer_ != nullptr &&
132 max_consumer_utilization_ != 132 max_consumer_utilization_ !=
133 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded) { 133 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded) {
134 consumer_feedback_observer_->OnUtilizationReport( 134 consumer_feedback_observer_->OnUtilizationReport(
135 frame_feedback_id_, max_consumer_utilization_); 135 frame_feedback_id_, max_consumer_utilization_);
136 } 136 }
137 if (frame_buffer_pool_ != nullptr) 137 if (frame_buffer_pool_ != nullptr)
138 frame_buffer_pool_->ReleaseBufferHold(buffer_id_); 138 frame_buffer_pool_->ReleaseBufferHold(buffer_id_);
139 max_consumer_utilization_ = 139 max_consumer_utilization_ =
140 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded; 140 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded;
141 } 141 }
142 } 142 }
143 143
144 bool VideoCaptureController::BufferState::HasZeroConsumerHoldCount() { 144 bool VideoCaptureController::BufferContext::HasZeroConsumerHoldCount() {
145 return consumer_hold_count_ == 0; 145 return consumer_hold_count_ == 0;
146 } 146 }
147 147
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() 148 VideoCaptureController::VideoCaptureController()
166 : frame_buffer_pool_(nullptr), 149 : frame_buffer_pool_(nullptr),
167 consumer_feedback_observer_(nullptr), 150 consumer_feedback_observer_(nullptr),
168 state_(VIDEO_CAPTURE_STATE_STARTED), 151 state_(VIDEO_CAPTURE_STATE_STARTED),
169 has_received_frames_(false), 152 has_received_frames_(false),
170 weak_ptr_factory_(this) { 153 weak_ptr_factory_(this) {
171 DCHECK_CURRENTLY_ON(BrowserThread::IO); 154 DCHECK_CURRENTLY_ON(BrowserThread::IO);
172 } 155 }
173 156
174 VideoCaptureController::~VideoCaptureController() = default; 157 VideoCaptureController::~VideoCaptureController() = default;
175 158
176 base::WeakPtr<VideoCaptureController> 159 base::WeakPtr<VideoCaptureController>
177 VideoCaptureController::GetWeakPtrForIOThread() { 160 VideoCaptureController::GetWeakPtrForIOThread() {
178 return weak_ptr_factory_.GetWeakPtr(); 161 return weak_ptr_factory_.GetWeakPtr();
179 } 162 }
180 163
181 void VideoCaptureController::SetFrameBufferPool( 164 void VideoCaptureController::SetFrameBufferPool(
182 std::unique_ptr<media::FrameBufferPool> frame_buffer_pool) { 165 std::unique_ptr<media::FrameBufferPool> frame_buffer_pool) {
183 DCHECK_CURRENTLY_ON(BrowserThread::IO); 166 DCHECK_CURRENTLY_ON(BrowserThread::IO);
184 frame_buffer_pool_ = std::move(frame_buffer_pool); 167 frame_buffer_pool_ = std::move(frame_buffer_pool);
185 // Update existing BufferState entries. 168 // Update existing BufferContext entries.
186 for (auto& entry : buffer_id_to_state_map_) 169 for (auto& entry : buffer_contexts_)
187 entry.second.SetFrameBufferPool(frame_buffer_pool_.get()); 170 entry.set_frame_buffer_pool(frame_buffer_pool_.get());
188 } 171 }
189 172
190 void VideoCaptureController::SetConsumerFeedbackObserver( 173 void VideoCaptureController::SetConsumerFeedbackObserver(
191 std::unique_ptr<media::VideoFrameConsumerFeedbackObserver> 174 std::unique_ptr<media::VideoFrameConsumerFeedbackObserver>
192 consumer_feedback_observer) { 175 consumer_feedback_observer) {
193 DCHECK_CURRENTLY_ON(BrowserThread::IO); 176 DCHECK_CURRENTLY_ON(BrowserThread::IO);
194 consumer_feedback_observer_ = std::move(consumer_feedback_observer); 177 consumer_feedback_observer_ = std::move(consumer_feedback_observer);
195 // Update existing BufferState entries. 178 // Update existing BufferContext entries.
196 for (auto& entry : buffer_id_to_state_map_) 179 for (auto& entry : buffer_contexts_)
197 entry.second.SetConsumerFeedbackObserver(consumer_feedback_observer_.get()); 180 entry.set_consumer_feedback_observer(consumer_feedback_observer_.get());
198 } 181 }
199 182
200 void VideoCaptureController::AddClient( 183 void VideoCaptureController::AddClient(
201 VideoCaptureControllerID id, 184 VideoCaptureControllerID id,
202 VideoCaptureControllerEventHandler* event_handler, 185 VideoCaptureControllerEventHandler* event_handler,
203 media::VideoCaptureSessionId session_id, 186 media::VideoCaptureSessionId session_id,
204 const media::VideoCaptureParams& params) { 187 const media::VideoCaptureParams& params) {
205 DCHECK_CURRENTLY_ON(BrowserThread::IO); 188 DCHECK_CURRENTLY_ON(BrowserThread::IO);
206 DVLOG(1) << "VideoCaptureController::AddClient() -- id=" << id 189 DVLOG(1) << "VideoCaptureController::AddClient() -- id=" << id
207 << ", session_id=" << session_id 190 << ", session_id=" << session_id << ", params.requested_format="
208 << ", params.requested_format="
209 << media::VideoCaptureFormat::ToString(params.requested_format); 191 << media::VideoCaptureFormat::ToString(params.requested_format);
210 192
211 // Check that requested VideoCaptureParams are valid and supported. If not, 193 // Check that requested VideoCaptureParams are valid and supported. If not,
212 // report an error immediately and punt. 194 // report an error immediately and punt.
213 if (!params.IsValid() || 195 if (!params.IsValid() ||
214 !(params.requested_format.pixel_format == media::PIXEL_FORMAT_I420 || 196 !(params.requested_format.pixel_format == media::PIXEL_FORMAT_I420 ||
215 params.requested_format.pixel_format == media::PIXEL_FORMAT_Y16) || 197 params.requested_format.pixel_format == media::PIXEL_FORMAT_Y16) ||
216 params.requested_format.pixel_storage != media::PIXEL_STORAGE_CPU) { 198 params.requested_format.pixel_storage != media::PIXEL_STORAGE_CPU) {
217 // Crash in debug builds since the renderer should not have asked for 199 // Crash in debug builds since the renderer should not have asked for
218 // invalid or unsupported parameters. 200 // invalid or unsupported parameters.
(...skipping 30 matching lines...) Expand all
249 int VideoCaptureController::RemoveClient( 231 int VideoCaptureController::RemoveClient(
250 VideoCaptureControllerID id, 232 VideoCaptureControllerID id,
251 VideoCaptureControllerEventHandler* event_handler) { 233 VideoCaptureControllerEventHandler* event_handler) {
252 DCHECK_CURRENTLY_ON(BrowserThread::IO); 234 DCHECK_CURRENTLY_ON(BrowserThread::IO);
253 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id; 235 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id;
254 236
255 ControllerClient* client = FindClient(id, event_handler, controller_clients_); 237 ControllerClient* client = FindClient(id, event_handler, controller_clients_);
256 if (!client) 238 if (!client)
257 return kInvalidMediaCaptureSessionId; 239 return kInvalidMediaCaptureSessionId;
258 240
259 // Take back all buffers held by the |client|. 241 for (const auto& buffer_id : client->buffers_in_use) {
260 for (const auto& buffer_id : client->buffers_in_use) 242 OnClientFinishedConsumingBuffer(
261 buffer_id_to_state_map_.at(buffer_id).DecreaseConsumerCount(); 243 client, buffer_id,
244 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded);
245 }
262 client->buffers_in_use.clear(); 246 client->buffers_in_use.clear();
263 247
264 int session_id = client->session_id; 248 int session_id = client->session_id;
265 controller_clients_.remove_if( 249 controller_clients_.remove_if(
266 [client](const std::unique_ptr<ControllerClient>& ptr) { 250 [client](const std::unique_ptr<ControllerClient>& ptr) {
267 return ptr.get() == client; 251 return ptr.get() == client;
268 }); 252 });
269 253
270 return session_id; 254 return session_id;
271 } 255 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 NOTREACHED(); 338 NOTREACHED();
355 return; 339 return;
356 } 340 }
357 auto buffers_in_use_entry_iter = 341 auto buffers_in_use_entry_iter =
358 std::find(std::begin(client->buffers_in_use), 342 std::find(std::begin(client->buffers_in_use),
359 std::end(client->buffers_in_use), buffer_id); 343 std::end(client->buffers_in_use), buffer_id);
360 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use)) { 344 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use)) {
361 NOTREACHED(); 345 NOTREACHED();
362 return; 346 return;
363 } 347 }
348 client->buffers_in_use.erase(buffers_in_use_entry_iter);
364 349
365 BufferState& buffer_state = buffer_id_to_state_map_.at(buffer_id); 350 OnClientFinishedConsumingBuffer(client, buffer_id,
366 buffer_state.RecordConsumerUtilization(consumer_resource_utilization); 351 consumer_resource_utilization);
367 buffer_state.DecreaseConsumerCount();
368 client->buffers_in_use.erase(buffers_in_use_entry_iter);
369 } 352 }
370 353
371 const media::VideoCaptureFormat& 354 const media::VideoCaptureFormat& VideoCaptureController::GetVideoCaptureFormat()
372 VideoCaptureController::GetVideoCaptureFormat() const { 355 const {
373 DCHECK_CURRENTLY_ON(BrowserThread::IO); 356 DCHECK_CURRENTLY_ON(BrowserThread::IO);
374 return video_capture_format_; 357 return video_capture_format_;
375 } 358 }
376 359
377 void VideoCaptureController::OnIncomingCapturedVideoFrame( 360 void VideoCaptureController::OnIncomingCapturedVideoFrame(
378 media::VideoCaptureDevice::Client::Buffer buffer, 361 media::VideoCaptureDevice::Client::Buffer buffer,
379 scoped_refptr<VideoFrame> frame) { 362 scoped_refptr<VideoFrame> frame) {
380 DCHECK_CURRENTLY_ON(BrowserThread::IO); 363 DCHECK_CURRENTLY_ON(BrowserThread::IO);
381 const int buffer_id = buffer.id(); 364 const int buffer_id_from_producer = buffer.id();
382 DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId); 365 DCHECK_NE(buffer_id_from_producer, media::VideoCaptureBufferPool::kInvalidId);
383 366 auto buffer_context_iter =
384 // Insert if not exists. 367 FindUnretiredBufferContextFromBufferId(buffer_id_from_producer);
385 const auto insert_result = buffer_id_to_state_map_.insert(std::make_pair( 368 if (buffer_context_iter == buffer_contexts_.end()) {
386 buffer_id, BufferState(buffer_id, buffer.frame_feedback_id(), 369 // A new buffer has been shared with us. Create new BufferContext.
387 consumer_feedback_observer_.get(), 370 buffer_contexts_.emplace_back(
388 frame_buffer_pool_.get()))); 371 next_buffer_context_id_++, buffer_id_from_producer,
389 BufferState& buffer_state = insert_result.first->second; 372 consumer_feedback_observer_.get(), frame_buffer_pool_.get());
390 DCHECK(buffer_state.HasZeroConsumerHoldCount()); 373 buffer_context_iter = buffer_contexts_.end() - 1;
391 // If a BufferState for |buffer_id| already existed, we must update the 374 }
392 // |frame_feedback_id| of the existing entry. 375 buffer_context_iter->set_frame_feedback_id(buffer.frame_feedback_id());
393 if (!insert_result.second) 376 DCHECK(buffer_context_iter->HasZeroConsumerHoldCount());
394 buffer_state.SetFrameFeedbackId(buffer.frame_feedback_id()); 377 const int buffer_context_id = buffer_context_iter->buffer_context_id();
mcasas 2017/02/03 23:24:21 Move to l. 401? Only needed inside the for loop l.
chfremer 2017/02/06 18:16:35 Done.
395 378
396 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 379 if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
397 if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) { 380 if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) {
398 frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE, 381 frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE,
399 video_capture_format_.frame_rate); 382 video_capture_format_.frame_rate);
400 } 383 }
401 std::unique_ptr<base::DictionaryValue> metadata = 384 std::unique_ptr<base::DictionaryValue> metadata =
402 frame->metadata()->CopyInternalValues(); 385 frame->metadata()->CopyInternalValues();
403 386
404 // Only I420 and Y16 pixel formats are currently supported. 387 // Only I420 and Y16 pixel formats are currently supported.
405 DCHECK(frame->format() == media::PIXEL_FORMAT_I420 || 388 DCHECK(frame->format() == media::PIXEL_FORMAT_I420 ||
406 frame->format() == media::PIXEL_FORMAT_Y16) 389 frame->format() == media::PIXEL_FORMAT_Y16)
407 << "Unsupported pixel format: " 390 << "Unsupported pixel format: "
408 << media::VideoPixelFormatToString(frame->format()); 391 << media::VideoPixelFormatToString(frame->format());
409 392
410 // Sanity-checks to confirm |frame| is actually being backed by |buffer|. 393 // Sanity-checks to confirm |frame| is actually being backed by |buffer|.
411 auto buffer_access = 394 auto buffer_access =
412 buffer.handle_provider()->GetHandleForInProcessAccess(); 395 buffer.handle_provider()->GetHandleForInProcessAccess();
413 DCHECK(frame->storage_type() == media::VideoFrame::STORAGE_SHMEM); 396 DCHECK(frame->storage_type() == media::VideoFrame::STORAGE_SHMEM);
414 DCHECK(frame->data(media::VideoFrame::kYPlane) >= buffer_access->data() && 397 DCHECK(frame->data(media::VideoFrame::kYPlane) >= buffer_access->data() &&
415 (frame->data(media::VideoFrame::kYPlane) < 398 (frame->data(media::VideoFrame::kYPlane) <
416 (buffer_access->data() + buffer_access->mapped_size()))) 399 (buffer_access->data() + buffer_access->mapped_size())))
417 << "VideoFrame does not appear to be backed by Buffer"; 400 << "VideoFrame does not appear to be backed by Buffer";
418 401
419 for (const auto& client : controller_clients_) { 402 for (const auto& client : controller_clients_) {
420 if (client->session_closed || client->paused) 403 if (client->session_closed || client->paused)
421 continue; 404 continue;
422 405
423 // On the first use of a buffer on a client, share the memory handles. 406 // On the first use of a BufferContext on a client, share the memory
424 auto known_buffers_entry_iter = 407 // handles.
425 std::find(std::begin(client->known_buffers), 408 auto known_buffers_entry_iter = std::find(
426 std::end(client->known_buffers), buffer_id); 409 std::begin(client->known_buffer_context_ids),
410 std::end(client->known_buffer_context_ids), buffer_context_id);
427 bool is_new_buffer = false; 411 bool is_new_buffer = false;
428 if (known_buffers_entry_iter == std::end(client->known_buffers)) { 412 if (known_buffers_entry_iter ==
429 client->known_buffers.push_back(buffer_id); 413 std::end(client->known_buffer_context_ids)) {
414 client->known_buffer_context_ids.push_back(buffer_context_id);
430 is_new_buffer = true; 415 is_new_buffer = true;
431 } 416 }
432 if (is_new_buffer) { 417 if (is_new_buffer) {
433 mojo::ScopedSharedBufferHandle handle = 418 mojo::ScopedSharedBufferHandle handle =
434 buffer.handle_provider()->GetHandleForInterProcessTransit(); 419 buffer.handle_provider()->GetHandleForInterProcessTransit();
435 client->event_handler->OnBufferCreated( 420 client->event_handler->OnBufferCreated(
436 client->controller_id, std::move(handle), 421 client->controller_id, std::move(handle),
437 buffer_access->mapped_size(), buffer_id); 422 buffer_access->mapped_size(), buffer_context_id);
438 } 423 }
439 client->event_handler->OnBufferReady(client->controller_id, buffer_id, 424 client->event_handler->OnBufferReady(client->controller_id,
440 frame); 425 buffer_context_id, frame);
441 426
442 auto buffers_in_use_entry_iter = 427 auto buffers_in_use_entry_iter =
443 std::find(std::begin(client->buffers_in_use), 428 std::find(std::begin(client->buffers_in_use),
444 std::end(client->buffers_in_use), buffer_id); 429 std::end(client->buffers_in_use), buffer_context_id);
445 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use)) 430 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use))
446 client->buffers_in_use.push_back(buffer_id); 431 client->buffers_in_use.push_back(buffer_context_id);
447 else 432 else
448 DCHECK(false) << "Unexpected duplicate buffer: " << buffer_id; 433 DCHECK(false) << "Unexpected duplicate buffer: " << buffer_context_id;
449 buffer_state.IncreaseConsumerCount(); 434 buffer_context_iter->IncreaseConsumerCount();
450 } 435 }
451 } 436 }
452 437
453 if (!has_received_frames_) { 438 if (!has_received_frames_) {
454 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width", 439 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width",
455 frame->visible_rect().width()); 440 frame->visible_rect().width());
456 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height", 441 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height",
457 frame->visible_rect().height()); 442 frame->visible_rect().height());
458 UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio", 443 UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio",
459 frame->visible_rect().width(), 444 frame->visible_rect().width(),
460 frame->visible_rect().height()); 445 frame->visible_rect().height());
461 double frame_rate = 0.0f; 446 double frame_rate = 0.0f;
462 if (!frame->metadata()->GetDouble(VideoFrameMetadata::FRAME_RATE, 447 if (!frame->metadata()->GetDouble(VideoFrameMetadata::FRAME_RATE,
463 &frame_rate)) { 448 &frame_rate)) {
464 frame_rate = video_capture_format_.frame_rate; 449 frame_rate = video_capture_format_.frame_rate;
465 } 450 }
466 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", frame_rate); 451 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", frame_rate);
467 has_received_frames_ = true; 452 has_received_frames_ = true;
468 } 453 }
469 } 454 }
470 455
471 void VideoCaptureController::OnError() { 456 void VideoCaptureController::OnError() {
472 DCHECK_CURRENTLY_ON(BrowserThread::IO); 457 DCHECK_CURRENTLY_ON(BrowserThread::IO);
473 state_ = VIDEO_CAPTURE_STATE_ERROR; 458 state_ = VIDEO_CAPTURE_STATE_ERROR;
474 459
475 for (const auto& client : controller_clients_) { 460 for (const auto& client : controller_clients_) {
476 if (client->session_closed) 461 if (client->session_closed)
477 continue; 462 continue;
478 client->event_handler->OnError(client->controller_id); 463 client->event_handler->OnError(client->controller_id);
479 } 464 }
480 } 465 }
481 466
482 void VideoCaptureController::OnLog(const std::string& message) { 467 void VideoCaptureController::OnLog(const std::string& message) {
483 DCHECK_CURRENTLY_ON(BrowserThread::IO); 468 DCHECK_CURRENTLY_ON(BrowserThread::IO);
484 MediaStreamManager::SendMessageToNativeLog("Video capture: " + message); 469 MediaStreamManager::SendMessageToNativeLog("Video capture: " + message);
485 } 470 }
486 471
487 void VideoCaptureController::OnBufferDestroyed(int buffer_id_to_drop) { 472 void VideoCaptureController::OnBufferRetired(int buffer_id) {
488 DCHECK_CURRENTLY_ON(BrowserThread::IO); 473 DCHECK_CURRENTLY_ON(BrowserThread::IO);
489 474
490 for (const auto& client : controller_clients_) { 475 auto buffer_context_iter = FindUnretiredBufferContextFromBufferId(buffer_id);
491 if (client->session_closed) 476 DCHECK(buffer_context_iter != buffer_contexts_.end());
492 continue;
493 477
494 auto known_buffers_entry_iter = 478 // If there are any clients still using the buffer, we need to allow them
495 std::find(std::begin(client->known_buffers), 479 // to finish up. We need to hold on to the BufferContext entry until then,
496 std::end(client->known_buffers), buffer_id_to_drop); 480 // because it contains the consumer hold.
497 if (known_buffers_entry_iter != std::end(client->known_buffers)) { 481 if (buffer_context_iter->HasZeroConsumerHoldCount())
498 client->known_buffers.erase(known_buffers_entry_iter); 482 ReleaseBufferContext(buffer_context_iter);
499 client->event_handler->OnBufferDestroyed(client->controller_id, 483 else
500 buffer_id_to_drop); 484 buffer_context_iter->set_is_retired();
501 }
502 }
503
504 buffer_id_to_state_map_.erase(buffer_id_to_drop);
505 } 485 }
506 486
507 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( 487 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient(
508 VideoCaptureControllerID id, 488 VideoCaptureControllerID id,
509 VideoCaptureControllerEventHandler* handler, 489 VideoCaptureControllerEventHandler* handler,
510 const ControllerClients& clients) { 490 const ControllerClients& clients) {
511 for (const auto& client : clients) { 491 for (const auto& client : clients) {
512 if (client->controller_id == id && client->event_handler == handler) 492 if (client->controller_id == id && client->event_handler == handler)
513 return client.get(); 493 return client.get();
514 } 494 }
515 return nullptr; 495 return nullptr;
516 } 496 }
517 497
518 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( 498 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient(
519 int session_id, 499 int session_id,
520 const ControllerClients& clients) { 500 const ControllerClients& clients) {
521 for (const auto& client : clients) { 501 for (const auto& client : clients) {
522 if (client->session_id == session_id) 502 if (client->session_id == session_id)
523 return client.get(); 503 return client.get();
524 } 504 }
525 return nullptr; 505 return nullptr;
526 } 506 }
527 507
508 std::vector<VideoCaptureController::BufferContext>::iterator
509 VideoCaptureController::FindBufferContextFromBufferContextId(
510 int buffer_context_id) {
511 auto buffer_context_iter =
512 std::find_if(buffer_contexts_.begin(), buffer_contexts_.end(),
513 [buffer_context_id](const BufferContext& entry) {
514 return entry.buffer_context_id() == buffer_context_id;
515 });
516 return buffer_context_iter;
mcasas 2017/02/03 23:24:21 return directly the std::find() statement? Also i
chfremer 2017/02/06 18:16:34 Done.
517 }
518
519 std::vector<VideoCaptureController::BufferContext>::iterator
520 VideoCaptureController::FindUnretiredBufferContextFromBufferId(int buffer_id) {
521 auto buffer_context_iter =
522 std::find_if(buffer_contexts_.begin(), buffer_contexts_.end(),
523 [buffer_id](const BufferContext& entry) {
524 return (entry.buffer_id() == buffer_id) &&
525 (entry.is_retired() == false);
526 });
527 return buffer_context_iter;
528 }
529
530 void VideoCaptureController::OnClientFinishedConsumingBuffer(
531 ControllerClient* client,
532 int buffer_context_id,
533 double consumer_resource_utilization) {
534 auto buffer_context_iter =
535 FindBufferContextFromBufferContextId(buffer_context_id);
536 DCHECK(buffer_context_iter != buffer_contexts_.end());
537
538 buffer_context_iter->RecordConsumerUtilization(consumer_resource_utilization);
539 buffer_context_iter->DecreaseConsumerCount();
540 if (buffer_context_iter->HasZeroConsumerHoldCount() &&
541 buffer_context_iter->is_retired()) {
542 ReleaseBufferContext(buffer_context_iter);
543 }
544 }
545
546 void VideoCaptureController::ReleaseBufferContext(
547 const std::vector<BufferContext>::iterator& buffer_context_iter) {
548 for (const auto& client : controller_clients_) {
549 if (client->session_closed)
550 continue;
551 auto entry_iter = std::find(std::begin(client->known_buffer_context_ids),
552 std::end(client->known_buffer_context_ids),
553 buffer_context_iter->buffer_context_id());
554 if (entry_iter != std::end(client->known_buffer_context_ids)) {
555 client->known_buffer_context_ids.erase(entry_iter);
556 client->event_handler->OnBufferDestroyed(
557 client->controller_id, buffer_context_iter->buffer_context_id());
558 }
559 }
560 buffer_contexts_.erase(buffer_context_iter);
561 }
562
528 } // namespace content 563 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698