| 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> |
| 11 #include <set> | 11 #include <set> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 16 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 17 #include "base/metrics/sparse_histogram.h" | 17 #include "base/metrics/sparse_histogram.h" |
| 18 #include "build/build_config.h" | 18 #include "build/build_config.h" |
| 19 #include "components/display_compositor/gl_helper.h" | 19 #include "components/display_compositor/gl_helper.h" |
| 20 #include "content/browser/renderer_host/media/media_stream_manager.h" | 20 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 21 #include "content/browser/renderer_host/media/video_capture_manager.h" | 21 #include "content/browser/renderer_host/media/video_capture_manager.h" |
| 22 #include "content/common/video_capture.mojom.h" |
| 22 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
| 23 #include "content/public/common/content_switches.h" | 24 #include "content/public/common/content_switches.h" |
| 24 #include "media/base/video_frame.h" | 25 #include "media/base/video_frame.h" |
| 25 #include "media/capture/video/video_capture_buffer_pool.h" | 26 #include "media/capture/video/video_capture_buffer_pool.h" |
| 26 #include "media/capture/video/video_capture_buffer_tracker_factory_impl.h" | 27 #include "media/capture/video/video_capture_buffer_tracker_factory_impl.h" |
| 27 #include "media/capture/video/video_capture_device_client.h" | 28 #include "media/capture/video/video_capture_device_client.h" |
| 28 #include "mojo/public/cpp/system/platform_handle.h" | 29 #include "mojo/public/cpp/system/platform_handle.h" |
| 29 | 30 |
| 30 #if !defined(OS_ANDROID) | 31 #if !defined(OS_ANDROID) |
| 31 #include "content/browser/compositor/image_transport_factory.h" | 32 #include "content/browser/compositor/image_transport_factory.h" |
| 32 #endif | 33 #endif |
| 33 | 34 |
| 34 using media::VideoCaptureFormat; | 35 using media::VideoCaptureFormat; |
| 35 using media::VideoFrame; | 36 using media::VideoFrame; |
| 36 using media::VideoFrameMetadata; | 37 using media::VideoFrameMetadata; |
| 37 | 38 |
| 38 namespace content { | 39 namespace content { |
| 39 | 40 |
| 40 namespace { | 41 namespace { |
| 41 | 42 |
| 42 static const int kInfiniteRatio = 99999; | 43 static const int kInfiniteRatio = 99999; |
| 43 | 44 |
| 44 #define UMA_HISTOGRAM_ASPECT_RATIO(name, width, height) \ | 45 #define UMA_HISTOGRAM_ASPECT_RATIO(name, width, height) \ |
| 45 UMA_HISTOGRAM_SPARSE_SLOWLY( \ | 46 UMA_HISTOGRAM_SPARSE_SLOWLY( \ |
| 46 name, \ | 47 name, \ |
| 47 (height) ? ((width) * 100) / (height) : kInfiniteRatio); | 48 (height) ? ((width) * 100) / (height) : kInfiniteRatio); |
| 48 | 49 |
| 50 // This manual copy routine is needed because base::DictionaryValue does not |
| 51 // allow the default copy operator. |
| 52 media::mojom::VideoFrameInfoPtr CloneFrameInfo( |
| 53 media::mojom::VideoFrameInfoPtr* frame_info) { |
| 54 auto result = media::mojom::VideoFrameInfo::New(); |
| 55 result->timestamp = (*frame_info)->timestamp; |
| 56 result->pixel_format = (*frame_info)->pixel_format; |
| 57 result->storage_type = (*frame_info)->storage_type; |
| 58 result->coded_size = (*frame_info)->coded_size; |
| 59 result->visible_rect = (*frame_info)->visible_rect; |
| 60 result->metadata = base::MakeUnique<base::DictionaryValue>(); |
| 61 result->metadata->MergeDictionary((*frame_info)->metadata.get()); |
| 62 return result; |
| 63 } |
| 64 |
| 49 } // anonymous namespace | 65 } // anonymous namespace |
| 50 | 66 |
| 51 struct VideoCaptureController::ControllerClient { | 67 struct VideoCaptureController::ControllerClient { |
| 52 ControllerClient(VideoCaptureControllerID id, | 68 ControllerClient(VideoCaptureControllerID id, |
| 53 VideoCaptureControllerEventHandler* handler, | 69 VideoCaptureControllerEventHandler* handler, |
| 54 media::VideoCaptureSessionId session_id, | 70 media::VideoCaptureSessionId session_id, |
| 55 const media::VideoCaptureParams& params) | 71 const media::VideoCaptureParams& params) |
| 56 : controller_id(id), | 72 : controller_id(id), |
| 57 event_handler(handler), | 73 event_handler(handler), |
| 58 session_id(session_id), | 74 session_id(session_id), |
| (...skipping 28 matching lines...) Expand all Loading... |
| 87 // simplify the code in both places. | 103 // simplify the code in both places. |
| 88 bool session_closed; | 104 bool session_closed; |
| 89 | 105 |
| 90 // Indicates whether the client is paused, if true, VideoCaptureController | 106 // Indicates whether the client is paused, if true, VideoCaptureController |
| 91 // stops updating its buffer. | 107 // stops updating its buffer. |
| 92 bool paused; | 108 bool paused; |
| 93 }; | 109 }; |
| 94 | 110 |
| 95 VideoCaptureController::BufferState::BufferState( | 111 VideoCaptureController::BufferState::BufferState( |
| 96 int buffer_id, | 112 int buffer_id, |
| 97 int frame_feedback_id, | |
| 98 media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer, | 113 media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer, |
| 99 media::FrameBufferPool* frame_buffer_pool) | 114 mojo::ScopedSharedBufferHandle handle) |
| 100 : buffer_id_(buffer_id), | 115 : buffer_id_(buffer_id), |
| 101 frame_feedback_id_(frame_feedback_id), | 116 frame_feedback_id_(0), |
| 102 consumer_feedback_observer_(consumer_feedback_observer), | 117 consumer_feedback_observer_(consumer_feedback_observer), |
| 103 frame_buffer_pool_(frame_buffer_pool), | 118 buffer_handle_(std::move(handle)), |
| 104 max_consumer_utilization_( | 119 max_consumer_utilization_( |
| 105 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded), | 120 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded), |
| 106 consumer_hold_count_(0) {} | 121 consumer_hold_count_(0) {} |
| 107 | 122 |
| 108 VideoCaptureController::BufferState::~BufferState() = default; | 123 VideoCaptureController::BufferState::~BufferState() = default; |
| 109 | 124 |
| 110 VideoCaptureController::BufferState::BufferState( | 125 VideoCaptureController::BufferState::BufferState( |
| 111 const VideoCaptureController::BufferState& other) = default; | 126 VideoCaptureController::BufferState&& other) = default; |
| 127 |
| 128 VideoCaptureController::BufferState& VideoCaptureController::BufferState:: |
| 129 operator=(BufferState&& other) = default; |
| 130 |
| 131 void VideoCaptureController::BufferState::set_read_permission( |
| 132 std::unique_ptr<media::Ownership> buffer_read_permission) { |
| 133 buffer_read_permission_ = std::move(buffer_read_permission); |
| 134 } |
| 135 |
| 136 void VideoCaptureController::BufferState::set_frame_feedback_id( |
| 137 int frame_feedback_id) { |
| 138 frame_feedback_id_ = frame_feedback_id; |
| 139 } |
| 112 | 140 |
| 113 void VideoCaptureController::BufferState::RecordConsumerUtilization( | 141 void VideoCaptureController::BufferState::RecordConsumerUtilization( |
| 114 double utilization) { | 142 double utilization) { |
| 115 if (std::isfinite(utilization) && utilization >= 0.0) { | 143 if (std::isfinite(utilization) && utilization >= 0.0) { |
| 116 max_consumer_utilization_ = | 144 max_consumer_utilization_ = |
| 117 std::max(max_consumer_utilization_, utilization); | 145 std::max(max_consumer_utilization_, utilization); |
| 118 } | 146 } |
| 119 } | 147 } |
| 120 | 148 |
| 121 void VideoCaptureController::BufferState::IncreaseConsumerCount() { | 149 void VideoCaptureController::BufferState::IncreaseConsumerCount() { |
| 122 if (consumer_hold_count_ == 0) | |
| 123 if (frame_buffer_pool_ != nullptr) | |
| 124 frame_buffer_pool_->SetBufferHold(buffer_id_); | |
| 125 consumer_hold_count_++; | 150 consumer_hold_count_++; |
| 126 } | 151 } |
| 127 | 152 |
| 128 void VideoCaptureController::BufferState::DecreaseConsumerCount() { | 153 void VideoCaptureController::BufferState::DecreaseConsumerCount() { |
| 154 LOG(ERROR) << "1"; |
| 129 consumer_hold_count_--; | 155 consumer_hold_count_--; |
| 130 if (consumer_hold_count_ == 0) { | 156 if (consumer_hold_count_ == 0) { |
| 131 if (consumer_feedback_observer_ != nullptr && | 157 if (consumer_feedback_observer_ != nullptr && |
| 132 max_consumer_utilization_ != | 158 max_consumer_utilization_ != |
| 133 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded) { | 159 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded) { |
| 134 consumer_feedback_observer_->OnUtilizationReport( | 160 consumer_feedback_observer_->OnUtilizationReport( |
| 135 frame_feedback_id_, max_consumer_utilization_); | 161 frame_feedback_id_, max_consumer_utilization_); |
| 136 } | 162 } |
| 137 if (frame_buffer_pool_ != nullptr) | 163 buffer_read_permission_.reset(); |
| 138 frame_buffer_pool_->ReleaseBufferHold(buffer_id_); | |
| 139 max_consumer_utilization_ = | 164 max_consumer_utilization_ = |
| 140 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded; | 165 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded; |
| 141 } | 166 } |
| 142 } | 167 } |
| 143 | 168 |
| 144 bool VideoCaptureController::BufferState::HasZeroConsumerHoldCount() { | 169 bool VideoCaptureController::BufferState::HasZeroConsumerHoldCount() { |
| 145 return consumer_hold_count_ == 0; | 170 return consumer_hold_count_ == 0; |
| 146 } | 171 } |
| 147 | 172 |
| 173 mojo::ScopedSharedBufferHandle |
| 174 VideoCaptureController::BufferState::CreateHandleCopy() { |
| 175 return buffer_handle_->Clone(); |
| 176 } |
| 177 |
| 148 void VideoCaptureController::BufferState::SetConsumerFeedbackObserver( | 178 void VideoCaptureController::BufferState::SetConsumerFeedbackObserver( |
| 149 media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer) { | 179 media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer) { |
| 150 consumer_feedback_observer_ = consumer_feedback_observer; | 180 consumer_feedback_observer_ = consumer_feedback_observer; |
| 151 } | 181 } |
| 152 | 182 |
| 153 void VideoCaptureController::BufferState::SetFrameBufferPool( | |
| 154 media::FrameBufferPool* frame_buffer_pool) { | |
| 155 frame_buffer_pool_ = frame_buffer_pool; | |
| 156 } | |
| 157 | |
| 158 VideoCaptureController::VideoCaptureController() | 183 VideoCaptureController::VideoCaptureController() |
| 159 : frame_buffer_pool_(nullptr), | 184 : consumer_feedback_observer_(nullptr), |
| 160 consumer_feedback_observer_(nullptr), | |
| 161 state_(VIDEO_CAPTURE_STATE_STARTED), | 185 state_(VIDEO_CAPTURE_STATE_STARTED), |
| 162 has_received_frames_(false), | 186 has_received_frames_(false), |
| 163 weak_ptr_factory_(this) { | 187 weak_ptr_factory_(this) { |
| 164 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 188 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 165 } | 189 } |
| 166 | 190 |
| 167 VideoCaptureController::~VideoCaptureController() = default; | 191 VideoCaptureController::~VideoCaptureController() = default; |
| 168 | 192 |
| 169 base::WeakPtr<VideoCaptureController> | 193 base::WeakPtr<VideoCaptureController> |
| 170 VideoCaptureController::GetWeakPtrForIOThread() { | 194 VideoCaptureController::GetWeakPtrForIOThread() { |
| 171 return weak_ptr_factory_.GetWeakPtr(); | 195 return weak_ptr_factory_.GetWeakPtr(); |
| 172 } | 196 } |
| 173 | 197 |
| 174 void VideoCaptureController::SetFrameBufferPool( | |
| 175 std::unique_ptr<media::FrameBufferPool> frame_buffer_pool) { | |
| 176 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 177 frame_buffer_pool_ = std::move(frame_buffer_pool); | |
| 178 // Update existing BufferState entries. | |
| 179 for (auto& entry : buffer_id_to_state_map_) | |
| 180 entry.second.SetFrameBufferPool(frame_buffer_pool_.get()); | |
| 181 } | |
| 182 | |
| 183 void VideoCaptureController::SetConsumerFeedbackObserver( | 198 void VideoCaptureController::SetConsumerFeedbackObserver( |
| 184 std::unique_ptr<media::VideoFrameConsumerFeedbackObserver> | 199 std::unique_ptr<media::VideoFrameConsumerFeedbackObserver> |
| 185 consumer_feedback_observer) { | 200 consumer_feedback_observer) { |
| 186 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 201 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 187 consumer_feedback_observer_ = std::move(consumer_feedback_observer); | 202 consumer_feedback_observer_ = std::move(consumer_feedback_observer); |
| 188 // Update existing BufferState entries. | 203 // Update existing BufferState entries. |
| 189 for (auto& entry : buffer_id_to_state_map_) | 204 for (auto& entry : buffer_states_) |
| 190 entry.second.SetConsumerFeedbackObserver(consumer_feedback_observer_.get()); | 205 entry.SetConsumerFeedbackObserver(consumer_feedback_observer_.get()); |
| 191 } | 206 } |
| 192 | 207 |
| 193 void VideoCaptureController::AddClient( | 208 void VideoCaptureController::AddClient( |
| 194 VideoCaptureControllerID id, | 209 VideoCaptureControllerID id, |
| 195 VideoCaptureControllerEventHandler* event_handler, | 210 VideoCaptureControllerEventHandler* event_handler, |
| 196 media::VideoCaptureSessionId session_id, | 211 media::VideoCaptureSessionId session_id, |
| 197 const media::VideoCaptureParams& params) { | 212 const media::VideoCaptureParams& params) { |
| 198 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 213 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 199 DVLOG(1) << "VideoCaptureController::AddClient() -- id=" << id | 214 DVLOG(1) << "VideoCaptureController::AddClient() -- id=" << id |
| 200 << ", session_id=" << session_id | 215 << ", session_id=" << session_id |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 int VideoCaptureController::RemoveClient( | 257 int VideoCaptureController::RemoveClient( |
| 243 VideoCaptureControllerID id, | 258 VideoCaptureControllerID id, |
| 244 VideoCaptureControllerEventHandler* event_handler) { | 259 VideoCaptureControllerEventHandler* event_handler) { |
| 245 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 260 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 246 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id; | 261 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id; |
| 247 | 262 |
| 248 ControllerClient* client = FindClient(id, event_handler, controller_clients_); | 263 ControllerClient* client = FindClient(id, event_handler, controller_clients_); |
| 249 if (!client) | 264 if (!client) |
| 250 return kInvalidMediaCaptureSessionId; | 265 return kInvalidMediaCaptureSessionId; |
| 251 | 266 |
| 252 // Take back all buffers held by the |client|. | 267 for (const auto& buffer_id : client->buffers_in_use) { |
| 253 for (const auto& buffer_id : client->buffers_in_use) | 268 OnClientFinishedConsumingBuffer( |
| 254 buffer_id_to_state_map_.at(buffer_id).DecreaseConsumerCount(); | 269 client, buffer_id, |
| 270 media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded); |
| 271 } |
| 255 client->buffers_in_use.clear(); | 272 client->buffers_in_use.clear(); |
| 256 | 273 |
| 257 int session_id = client->session_id; | 274 int session_id = client->session_id; |
| 258 controller_clients_.remove_if( | 275 controller_clients_.remove_if( |
| 259 [client](const std::unique_ptr<ControllerClient>& ptr) { | 276 [client](const std::unique_ptr<ControllerClient>& ptr) { |
| 260 return ptr.get() == client; | 277 return ptr.get() == client; |
| 261 }); | 278 }); |
| 262 | 279 |
| 263 return session_id; | 280 return session_id; |
| 264 } | 281 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 NOTREACHED(); | 365 NOTREACHED(); |
| 349 return; | 366 return; |
| 350 } | 367 } |
| 351 auto buffers_in_use_entry_iter = | 368 auto buffers_in_use_entry_iter = |
| 352 std::find(std::begin(client->buffers_in_use), | 369 std::find(std::begin(client->buffers_in_use), |
| 353 std::end(client->buffers_in_use), buffer_id); | 370 std::end(client->buffers_in_use), buffer_id); |
| 354 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use)) { | 371 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use)) { |
| 355 NOTREACHED(); | 372 NOTREACHED(); |
| 356 return; | 373 return; |
| 357 } | 374 } |
| 375 client->buffers_in_use.erase(buffers_in_use_entry_iter); |
| 358 | 376 |
| 359 BufferState& buffer_state = buffer_id_to_state_map_.at(buffer_id); | 377 OnClientFinishedConsumingBuffer(client, buffer_id, |
| 360 buffer_state.RecordConsumerUtilization(consumer_resource_utilization); | 378 consumer_resource_utilization); |
| 361 buffer_state.DecreaseConsumerCount(); | |
| 362 client->buffers_in_use.erase(buffers_in_use_entry_iter); | |
| 363 } | 379 } |
| 364 | 380 |
| 365 const media::VideoCaptureFormat& | 381 const media::VideoCaptureFormat& |
| 366 VideoCaptureController::GetVideoCaptureFormat() const { | 382 VideoCaptureController::GetVideoCaptureFormat() const { |
| 367 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 383 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 368 return video_capture_format_; | 384 return video_capture_format_; |
| 369 } | 385 } |
| 370 | 386 |
| 371 void VideoCaptureController::OnIncomingCapturedVideoFrame( | 387 void VideoCaptureController::OnNewBufferHandle( |
| 372 media::VideoCaptureDevice::Client::Buffer buffer, | 388 int buffer_id, |
| 373 scoped_refptr<VideoFrame> frame) { | 389 std::unique_ptr<media::BufferHandleProvider> handle_provider) { |
| 374 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 390 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 375 const int buffer_id = buffer.id(); | 391 DCHECK(std::find_if(buffer_states_.begin(), buffer_states_.end(), |
| 392 [buffer_id](const BufferState& entry) { |
| 393 return entry.buffer_id() == buffer_id; |
| 394 }) == buffer_states_.end()); |
| 395 buffer_states_.emplace_back( |
| 396 buffer_id, consumer_feedback_observer_.get(), |
| 397 handle_provider->GetHandleForInterProcessTransit()); |
| 398 } |
| 399 |
| 400 void VideoCaptureController::OnFrameReadyInBuffer( |
| 401 int buffer_id, |
| 402 int frame_feedback_id, |
| 403 std::unique_ptr<media::Ownership> buffer_read_permission, |
| 404 media::mojom::VideoFrameInfoPtr frame_info) { |
| 405 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 376 DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId); | 406 DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId); |
| 377 | 407 |
| 378 // Insert if not exists. | 408 auto buffer_state_iter = |
| 379 const auto it = | 409 std::find_if(buffer_states_.begin(), buffer_states_.end(), |
| 380 buffer_id_to_state_map_ | 410 [buffer_id](const BufferState& entry) { |
| 381 .insert(std::make_pair( | 411 return entry.buffer_id() == buffer_id; |
| 382 buffer_id, BufferState(buffer_id, buffer.frame_feedback_id(), | 412 }); |
| 383 consumer_feedback_observer_.get(), | 413 DCHECK(buffer_state_iter != buffer_states_.end()); |
| 384 frame_buffer_pool_.get()))) | 414 DCHECK(buffer_state_iter->HasZeroConsumerHoldCount()); |
| 385 .first; | 415 buffer_state_iter->set_frame_feedback_id(frame_feedback_id); |
| 386 BufferState& buffer_state = it->second; | |
| 387 DCHECK(buffer_state.HasZeroConsumerHoldCount()); | |
| 388 | 416 |
| 389 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 417 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 390 if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) { | |
| 391 frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE, | |
| 392 video_capture_format_.frame_rate); | |
| 393 } | |
| 394 std::unique_ptr<base::DictionaryValue> metadata = | |
| 395 frame->metadata()->CopyInternalValues(); | |
| 396 | |
| 397 // Only I420 and Y16 pixel formats are currently supported. | |
| 398 DCHECK(frame->format() == media::PIXEL_FORMAT_I420 || | |
| 399 frame->format() == media::PIXEL_FORMAT_Y16) | |
| 400 << "Unsupported pixel format: " | |
| 401 << media::VideoPixelFormatToString(frame->format()); | |
| 402 | |
| 403 // Sanity-checks to confirm |frame| is actually being backed by |buffer|. | |
| 404 auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess(); | |
| 405 DCHECK(frame->storage_type() == media::VideoFrame::STORAGE_SHMEM); | |
| 406 DCHECK(frame->data(media::VideoFrame::kYPlane) >= buffer_access->data() && | |
| 407 (frame->data(media::VideoFrame::kYPlane) < | |
| 408 (buffer_access->data() + buffer_access->mapped_size()))) | |
| 409 << "VideoFrame does not appear to be backed by Buffer"; | |
| 410 | |
| 411 for (const auto& client : controller_clients_) { | 418 for (const auto& client : controller_clients_) { |
| 412 if (client->session_closed || client->paused) | 419 if (client->session_closed || client->paused) |
| 413 continue; | 420 continue; |
| 414 | 421 |
| 415 // On the first use of a buffer on a client, share the memory handles. | 422 // On the first use of a buffer on a client, call OnBufferCreated(). |
| 416 auto known_buffers_entry_iter = | 423 auto known_buffers_entry_iter = |
| 417 std::find(std::begin(client->known_buffers), | 424 std::find(std::begin(client->known_buffers), |
| 418 std::end(client->known_buffers), buffer_id); | 425 std::end(client->known_buffers), buffer_id); |
| 419 bool is_new_buffer = false; | 426 bool is_new_buffer = false; |
| 420 if (known_buffers_entry_iter == std::end(client->known_buffers)) { | 427 if (known_buffers_entry_iter == std::end(client->known_buffers)) { |
| 421 client->known_buffers.push_back(buffer_id); | 428 client->known_buffers.push_back(buffer_id); |
| 422 is_new_buffer = true; | 429 is_new_buffer = true; |
| 423 } | 430 } |
| 424 if (is_new_buffer) { | 431 if (is_new_buffer) { |
| 425 mojo::ScopedSharedBufferHandle handle = | 432 size_t mapped_size = |
| 426 buffer.handle_provider->GetHandleForInterProcessTransit(); | 433 media::VideoCaptureFormat(frame_info->coded_size, 0.0f, |
| 434 frame_info->pixel_format, |
| 435 frame_info->storage_type) |
| 436 .ImageAllocationSize(); |
| 427 client->event_handler->OnBufferCreated( | 437 client->event_handler->OnBufferCreated( |
| 428 client->controller_id, std::move(handle), | 438 client->controller_id, buffer_state_iter->CreateHandleCopy(), |
| 429 buffer_access->mapped_size(), buffer_id); | 439 mapped_size, buffer_id); |
| 430 } | 440 } |
| 441 |
| 442 auto frame_info_copy = CloneFrameInfo(&frame_info); |
| 431 client->event_handler->OnBufferReady(client->controller_id, buffer_id, | 443 client->event_handler->OnBufferReady(client->controller_id, buffer_id, |
| 432 frame); | 444 std::move(frame_info_copy)); |
| 433 | |
| 434 auto buffers_in_use_entry_iter = | 445 auto buffers_in_use_entry_iter = |
| 435 std::find(std::begin(client->buffers_in_use), | 446 std::find(std::begin(client->buffers_in_use), |
| 436 std::end(client->buffers_in_use), buffer_id); | 447 std::end(client->buffers_in_use), buffer_id); |
| 437 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use)) | 448 if (buffers_in_use_entry_iter == std::end(client->buffers_in_use)) |
| 438 client->buffers_in_use.push_back(buffer_id); | 449 client->buffers_in_use.push_back(buffer_id); |
| 439 else | 450 else |
| 440 DCHECK(false) << "Unexpected duplicate buffer: " << buffer_id; | 451 DCHECK(false) << "Unexpected duplicate buffer: " << buffer_id; |
| 441 buffer_state.IncreaseConsumerCount(); | 452 // Use if-check, because we are in a loop and only want to do this |
| 453 // move operation once. |
| 454 if (buffer_read_permission) { |
| 455 buffer_state_iter->set_read_permission( |
| 456 std::move(buffer_read_permission)); |
| 457 } |
| 458 buffer_state_iter->IncreaseConsumerCount(); |
| 442 } | 459 } |
| 443 } | 460 } |
| 444 | 461 |
| 445 if (!has_received_frames_) { | 462 if (!has_received_frames_) { |
| 446 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width", | 463 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width", |
| 447 frame->visible_rect().width()); | 464 frame_info->coded_size.width()); |
| 448 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height", | 465 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height", |
| 449 frame->visible_rect().height()); | 466 frame_info->coded_size.height()); |
| 450 UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio", | 467 UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio", |
| 451 frame->visible_rect().width(), | 468 frame_info->coded_size.width(), |
| 452 frame->visible_rect().height()); | 469 frame_info->coded_size.height()); |
| 453 double frame_rate = 0.0f; | 470 double frame_rate = 0.0f; |
| 454 if (!frame->metadata()->GetDouble(VideoFrameMetadata::FRAME_RATE, | 471 media::VideoFrameMetadata metadata; |
| 455 &frame_rate)) { | 472 metadata.MergeInternalValuesFrom(*frame_info->metadata); |
| 473 if (!metadata.GetDouble(VideoFrameMetadata::FRAME_RATE, &frame_rate)) { |
| 456 frame_rate = video_capture_format_.frame_rate; | 474 frame_rate = video_capture_format_.frame_rate; |
| 457 } | 475 } |
| 458 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", frame_rate); | 476 UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate", frame_rate); |
| 459 has_received_frames_ = true; | 477 has_received_frames_ = true; |
| 460 } | 478 } |
| 461 } | 479 } |
| 462 | 480 |
| 481 void VideoCaptureController::OnBufferRetired(int buffer_id) { |
| 482 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 483 |
| 484 auto buffer_state_iter = |
| 485 std::find_if(buffer_states_.begin(), buffer_states_.end(), |
| 486 [buffer_id](const BufferState& entry) { |
| 487 return entry.buffer_id() == buffer_id; |
| 488 }); |
| 489 DCHECK(buffer_state_iter != buffer_states_.end()); |
| 490 |
| 491 // If there are any clients still using the buffer, we need to allow them |
| 492 // to finish up. We need to hold on to the BufferState entry until then, |
| 493 // because it contains the |read_access_permission|. |
| 494 if (buffer_state_iter->HasZeroConsumerHoldCount()) { |
| 495 ReleaseBufferState(buffer_state_iter); |
| 496 } else { |
| 497 buffer_state_iter->set_is_retired(); |
| 498 } |
| 499 } |
| 500 |
| 463 void VideoCaptureController::OnError() { | 501 void VideoCaptureController::OnError() { |
| 464 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 502 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 465 state_ = VIDEO_CAPTURE_STATE_ERROR; | 503 state_ = VIDEO_CAPTURE_STATE_ERROR; |
| 466 | 504 |
| 467 for (const auto& client : controller_clients_) { | 505 for (const auto& client : controller_clients_) { |
| 468 if (client->session_closed) | 506 if (client->session_closed) |
| 469 continue; | 507 continue; |
| 470 client->event_handler->OnError(client->controller_id); | 508 client->event_handler->OnError(client->controller_id); |
| 471 } | 509 } |
| 472 } | 510 } |
| 473 | 511 |
| 474 void VideoCaptureController::OnLog(const std::string& message) { | 512 void VideoCaptureController::OnLog(const std::string& message) { |
| 475 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 513 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 476 MediaStreamManager::SendMessageToNativeLog("Video capture: " + message); | 514 MediaStreamManager::SendMessageToNativeLog("Video capture: " + message); |
| 477 } | 515 } |
| 478 | 516 |
| 479 void VideoCaptureController::OnBufferDestroyed(int buffer_id_to_drop) { | |
| 480 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 481 | |
| 482 for (const auto& client : controller_clients_) { | |
| 483 if (client->session_closed) | |
| 484 continue; | |
| 485 | |
| 486 auto known_buffers_entry_iter = | |
| 487 std::find(std::begin(client->known_buffers), | |
| 488 std::end(client->known_buffers), buffer_id_to_drop); | |
| 489 if (known_buffers_entry_iter != std::end(client->known_buffers)) { | |
| 490 client->known_buffers.erase(known_buffers_entry_iter); | |
| 491 client->event_handler->OnBufferDestroyed(client->controller_id, | |
| 492 buffer_id_to_drop); | |
| 493 } | |
| 494 } | |
| 495 | |
| 496 buffer_id_to_state_map_.erase(buffer_id_to_drop); | |
| 497 } | |
| 498 | |
| 499 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( | 517 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( |
| 500 VideoCaptureControllerID id, | 518 VideoCaptureControllerID id, |
| 501 VideoCaptureControllerEventHandler* handler, | 519 VideoCaptureControllerEventHandler* handler, |
| 502 const ControllerClients& clients) { | 520 const ControllerClients& clients) { |
| 503 for (const auto& client : clients) { | 521 for (const auto& client : clients) { |
| 504 if (client->controller_id == id && client->event_handler == handler) | 522 if (client->controller_id == id && client->event_handler == handler) |
| 505 return client.get(); | 523 return client.get(); |
| 506 } | 524 } |
| 507 return nullptr; | 525 return nullptr; |
| 508 } | 526 } |
| 509 | 527 |
| 510 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( | 528 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( |
| 511 int session_id, | 529 int session_id, |
| 512 const ControllerClients& clients) { | 530 const ControllerClients& clients) { |
| 513 for (const auto& client : clients) { | 531 for (const auto& client : clients) { |
| 514 if (client->session_id == session_id) | 532 if (client->session_id == session_id) |
| 515 return client.get(); | 533 return client.get(); |
| 516 } | 534 } |
| 517 return nullptr; | 535 return nullptr; |
| 518 } | 536 } |
| 519 | 537 |
| 538 void VideoCaptureController::OnClientFinishedConsumingBuffer( |
| 539 ControllerClient* client, |
| 540 int buffer_id, |
| 541 double consumer_resource_utilization) { |
| 542 auto buffer_state_iter = |
| 543 std::find_if(buffer_states_.begin(), buffer_states_.end(), |
| 544 [buffer_id](const BufferState& entry) { |
| 545 return entry.buffer_id() == buffer_id; |
| 546 }); |
| 547 DCHECK(buffer_state_iter != buffer_states_.end()); |
| 548 |
| 549 buffer_state_iter->RecordConsumerUtilization(consumer_resource_utilization); |
| 550 buffer_state_iter->DecreaseConsumerCount(); |
| 551 if (buffer_state_iter->HasZeroConsumerHoldCount() && |
| 552 buffer_state_iter->is_retired()) { |
| 553 ReleaseBufferState(buffer_state_iter); |
| 554 } |
| 555 } |
| 556 |
| 557 void VideoCaptureController::ReleaseBufferState( |
| 558 const std::vector<BufferState>::iterator& buffer_state_iter) { |
| 559 for (const auto& client : controller_clients_) { |
| 560 if (client->session_closed) |
| 561 continue; |
| 562 |
| 563 auto known_buffers_entry_iter = std::find(std::begin(client->known_buffers), |
| 564 std::end(client->known_buffers), |
| 565 buffer_state_iter->buffer_id()); |
| 566 if (known_buffers_entry_iter != std::end(client->known_buffers)) { |
| 567 client->known_buffers.erase(known_buffers_entry_iter); |
| 568 client->event_handler->OnBufferDestroyed(client->controller_id, |
| 569 buffer_state_iter->buffer_id()); |
| 570 } |
| 571 } |
| 572 buffer_states_.erase(buffer_state_iter); |
| 573 } |
| 574 |
| 520 } // namespace content | 575 } // namespace content |
| OLD | NEW |