Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |