| 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 "base/stl_util.h" | |
| 19 #include "build/build_config.h" | 18 #include "build/build_config.h" |
| 20 #include "components/display_compositor/gl_helper.h" | 19 #include "components/display_compositor/gl_helper.h" |
| 21 #include "content/browser/renderer_host/media/media_stream_manager.h" | 20 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 22 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" | 21 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" |
| 23 #include "content/browser/renderer_host/media/video_capture_device_client.h" | 22 #include "content/browser/renderer_host/media/video_capture_device_client.h" |
| 24 #include "content/browser/renderer_host/media/video_capture_manager.h" | 23 #include "content/browser/renderer_host/media/video_capture_manager.h" |
| 25 #include "content/public/browser/browser_thread.h" | 24 #include "content/public/browser/browser_thread.h" |
| 26 #include "content/public/common/content_switches.h" | 25 #include "content/public/common/content_switches.h" |
| 27 #include "media/base/video_frame.h" | 26 #include "media/base/video_frame.h" |
| 28 | 27 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 // Signal error in case device is already in error state. | 184 // Signal error in case device is already in error state. |
| 186 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { | 185 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { |
| 187 event_handler->OnError(id); | 186 event_handler->OnError(id); |
| 188 return; | 187 return; |
| 189 } | 188 } |
| 190 | 189 |
| 191 // Do nothing if this client has called AddClient before. | 190 // Do nothing if this client has called AddClient before. |
| 192 if (FindClient(id, event_handler, controller_clients_)) | 191 if (FindClient(id, event_handler, controller_clients_)) |
| 193 return; | 192 return; |
| 194 | 193 |
| 195 ControllerClient* client = new ControllerClient( | 194 std::unique_ptr<ControllerClient> client = base::MakeUnique<ControllerClient>( |
| 196 id, event_handler, render_process, session_id, params); | 195 id, event_handler, render_process, session_id, params); |
| 197 // If we already have gotten frame_info from the device, repeat it to the new | 196 // If we already have gotten frame_info from the device, repeat it to the new |
| 198 // client. | 197 // client. |
| 199 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 198 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 200 controller_clients_.push_back(client); | 199 controller_clients_.push_back(std::move(client)); |
| 201 return; | 200 return; |
| 202 } | 201 } |
| 203 } | 202 } |
| 204 | 203 |
| 205 int VideoCaptureController::RemoveClient( | 204 int VideoCaptureController::RemoveClient( |
| 206 VideoCaptureControllerID id, | 205 VideoCaptureControllerID id, |
| 207 VideoCaptureControllerEventHandler* event_handler) { | 206 VideoCaptureControllerEventHandler* event_handler) { |
| 208 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 207 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 209 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id; | 208 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id; |
| 210 | 209 |
| 211 ControllerClient* client = FindClient(id, event_handler, controller_clients_); | 210 ControllerClient* client = FindClient(id, event_handler, controller_clients_); |
| 212 if (!client) | 211 if (!client) |
| 213 return kInvalidMediaCaptureSessionId; | 212 return kInvalidMediaCaptureSessionId; |
| 214 | 213 |
| 215 // Take back all buffers held by the |client|. | 214 // Take back all buffers held by the |client|. |
| 216 for (const auto& buffer : client->active_buffers) | 215 for (const auto& buffer : client->active_buffers) |
| 217 buffer_pool_->RelinquishConsumerHold(buffer.first, 1); | 216 buffer_pool_->RelinquishConsumerHold(buffer.first, 1); |
| 218 client->active_buffers.clear(); | 217 client->active_buffers.clear(); |
| 219 | 218 |
| 220 int session_id = client->session_id; | 219 int session_id = client->session_id; |
| 221 controller_clients_.remove(client); | 220 controller_clients_.remove_if( |
| 222 delete client; | 221 [client](const std::unique_ptr<ControllerClient>& ptr) { |
| 222 return ptr.get() == client; |
| 223 }); |
| 223 | 224 |
| 224 return session_id; | 225 return session_id; |
| 225 } | 226 } |
| 226 | 227 |
| 227 void VideoCaptureController::PauseClient( | 228 void VideoCaptureController::PauseClient( |
| 228 VideoCaptureControllerID id, | 229 VideoCaptureControllerID id, |
| 229 VideoCaptureControllerEventHandler* event_handler) { | 230 VideoCaptureControllerEventHandler* event_handler) { |
| 230 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 231 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 231 DVLOG(1) << "VideoCaptureController::PauseClient, id " << id; | 232 DVLOG(1) << "VideoCaptureController::PauseClient, id " << id; |
| 232 | 233 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 258 return true; | 259 return true; |
| 259 } | 260 } |
| 260 | 261 |
| 261 int VideoCaptureController::GetClientCount() const { | 262 int VideoCaptureController::GetClientCount() const { |
| 262 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 263 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 263 return controller_clients_.size(); | 264 return controller_clients_.size(); |
| 264 } | 265 } |
| 265 | 266 |
| 266 bool VideoCaptureController::HasActiveClient() const { | 267 bool VideoCaptureController::HasActiveClient() const { |
| 267 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 268 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 268 for (ControllerClient* client : controller_clients_) { | 269 for (const auto& client : controller_clients_) { |
| 269 if (!client->paused) | 270 if (!client->paused) |
| 270 return true; | 271 return true; |
| 271 } | 272 } |
| 272 return false; | 273 return false; |
| 273 } | 274 } |
| 274 | 275 |
| 275 bool VideoCaptureController::HasPausedClient() const { | 276 bool VideoCaptureController::HasPausedClient() const { |
| 276 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 277 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 277 for (ControllerClient* client : controller_clients_) { | 278 for (const auto& client : controller_clients_) { |
| 278 if (client->paused) | 279 if (client->paused) |
| 279 return true; | 280 return true; |
| 280 } | 281 } |
| 281 return false; | 282 return false; |
| 282 } | 283 } |
| 283 | 284 |
| 284 void VideoCaptureController::StopSession(int session_id) { | 285 void VideoCaptureController::StopSession(int session_id) { |
| 285 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 286 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 286 DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id; | 287 DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id; |
| 287 | 288 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 base::Bind(&ReturnVideoFrame, frame, sync_token)); | 344 base::Bind(&ReturnVideoFrame, frame, sync_token)); |
| 344 } | 345 } |
| 345 | 346 |
| 346 const media::VideoCaptureFormat& | 347 const media::VideoCaptureFormat& |
| 347 VideoCaptureController::GetVideoCaptureFormat() const { | 348 VideoCaptureController::GetVideoCaptureFormat() const { |
| 348 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 349 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 349 return video_capture_format_; | 350 return video_capture_format_; |
| 350 } | 351 } |
| 351 | 352 |
| 352 VideoCaptureController::~VideoCaptureController() { | 353 VideoCaptureController::~VideoCaptureController() { |
| 353 base::STLDeleteContainerPointers(controller_clients_.begin(), | |
| 354 controller_clients_.end()); | |
| 355 } | 354 } |
| 356 | 355 |
| 357 void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread( | 356 void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread( |
| 358 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, | 357 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, |
| 359 const scoped_refptr<VideoFrame>& frame) { | 358 const scoped_refptr<VideoFrame>& frame) { |
| 360 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 359 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 361 const int buffer_id = buffer->id(); | 360 const int buffer_id = buffer->id(); |
| 362 DCHECK_NE(buffer_id, VideoCaptureBufferPool::kInvalidId); | 361 DCHECK_NE(buffer_id, VideoCaptureBufferPool::kInvalidId); |
| 363 | 362 |
| 364 int count = 0; | 363 int count = 0; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 379 // Sanity-checks to confirm |frame| is actually being backed by |buffer|. | 378 // Sanity-checks to confirm |frame| is actually being backed by |buffer|. |
| 380 DCHECK(frame->storage_type() == media::VideoFrame::STORAGE_SHMEM || | 379 DCHECK(frame->storage_type() == media::VideoFrame::STORAGE_SHMEM || |
| 381 (frame->storage_type() == | 380 (frame->storage_type() == |
| 382 media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS)); | 381 media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS)); |
| 383 DCHECK(frame->data(media::VideoFrame::kYPlane) >= buffer->data(0) && | 382 DCHECK(frame->data(media::VideoFrame::kYPlane) >= buffer->data(0) && |
| 384 (frame->data(media::VideoFrame::kYPlane) < | 383 (frame->data(media::VideoFrame::kYPlane) < |
| 385 (reinterpret_cast<const uint8_t*>(buffer->data(0)) + | 384 (reinterpret_cast<const uint8_t*>(buffer->data(0)) + |
| 386 buffer->mapped_size()))) | 385 buffer->mapped_size()))) |
| 387 << "VideoFrame does not appear to be backed by Buffer"; | 386 << "VideoFrame does not appear to be backed by Buffer"; |
| 388 | 387 |
| 389 for (auto* client : controller_clients_) { | 388 for (const auto& client : controller_clients_) { |
| 390 if (client->session_closed || client->paused) | 389 if (client->session_closed || client->paused) |
| 391 continue; | 390 continue; |
| 392 | 391 |
| 393 // On the first use of a buffer on a client, share the memory handles. | 392 // On the first use of a buffer on a client, share the memory handles. |
| 394 const bool is_new_buffer = client->known_buffers.insert(buffer_id).second; | 393 const bool is_new_buffer = client->known_buffers.insert(buffer_id).second; |
| 395 if (is_new_buffer) | 394 if (is_new_buffer) |
| 396 DoNewBufferOnIOThread(client, buffer.get(), frame); | 395 DoNewBufferOnIOThread(client.get(), buffer.get(), frame); |
| 397 | 396 |
| 398 client->event_handler->OnBufferReady(client->controller_id, buffer_id, | 397 client->event_handler->OnBufferReady(client->controller_id, buffer_id, |
| 399 frame); | 398 frame); |
| 400 const bool inserted = | 399 const bool inserted = |
| 401 client->active_buffers.insert(std::make_pair(buffer_id, frame)) | 400 client->active_buffers.insert(std::make_pair(buffer_id, frame)) |
| 402 .second; | 401 .second; |
| 403 DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer_id; | 402 DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer_id; |
| 404 count++; | 403 count++; |
| 405 } | 404 } |
| 406 } | 405 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 422 has_received_frames_ = true; | 421 has_received_frames_ = true; |
| 423 } | 422 } |
| 424 | 423 |
| 425 buffer_pool_->HoldForConsumers(buffer_id, count); | 424 buffer_pool_->HoldForConsumers(buffer_id, count); |
| 426 } | 425 } |
| 427 | 426 |
| 428 void VideoCaptureController::DoErrorOnIOThread() { | 427 void VideoCaptureController::DoErrorOnIOThread() { |
| 429 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 428 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 430 state_ = VIDEO_CAPTURE_STATE_ERROR; | 429 state_ = VIDEO_CAPTURE_STATE_ERROR; |
| 431 | 430 |
| 432 for (const auto* client : controller_clients_) { | 431 for (const auto& client : controller_clients_) { |
| 433 if (client->session_closed) | 432 if (client->session_closed) |
| 434 continue; | 433 continue; |
| 435 client->event_handler->OnError(client->controller_id); | 434 client->event_handler->OnError(client->controller_id); |
| 436 } | 435 } |
| 437 } | 436 } |
| 438 | 437 |
| 439 void VideoCaptureController::DoLogOnIOThread(const std::string& message) { | 438 void VideoCaptureController::DoLogOnIOThread(const std::string& message) { |
| 440 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 439 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 441 MediaStreamManager::SendMessageToNativeLog("Video capture: " + message); | 440 MediaStreamManager::SendMessageToNativeLog("Video capture: " + message); |
| 442 } | 441 } |
| 443 | 442 |
| 444 void VideoCaptureController::DoBufferDestroyedOnIOThread( | 443 void VideoCaptureController::DoBufferDestroyedOnIOThread( |
| 445 int buffer_id_to_drop) { | 444 int buffer_id_to_drop) { |
| 446 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 445 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 447 | 446 |
| 448 for (auto* client : controller_clients_) { | 447 for (const auto& client : controller_clients_) { |
| 449 if (client->session_closed) | 448 if (client->session_closed) |
| 450 continue; | 449 continue; |
| 451 | 450 |
| 452 if (client->known_buffers.erase(buffer_id_to_drop)) { | 451 if (client->known_buffers.erase(buffer_id_to_drop)) { |
| 453 client->event_handler->OnBufferDestroyed(client->controller_id, | 452 client->event_handler->OnBufferDestroyed(client->controller_id, |
| 454 buffer_id_to_drop); | 453 buffer_id_to_drop); |
| 455 } | 454 } |
| 456 } | 455 } |
| 457 } | 456 } |
| 458 | 457 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 489 default: | 488 default: |
| 490 NOTREACHED(); | 489 NOTREACHED(); |
| 491 break; | 490 break; |
| 492 } | 491 } |
| 493 } | 492 } |
| 494 | 493 |
| 495 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( | 494 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( |
| 496 VideoCaptureControllerID id, | 495 VideoCaptureControllerID id, |
| 497 VideoCaptureControllerEventHandler* handler, | 496 VideoCaptureControllerEventHandler* handler, |
| 498 const ControllerClients& clients) { | 497 const ControllerClients& clients) { |
| 499 for (auto* client : clients) { | 498 for (const auto& client : clients) { |
| 500 if (client->controller_id == id && client->event_handler == handler) | 499 if (client->controller_id == id && client->event_handler == handler) |
| 501 return client; | 500 return client.get(); |
| 502 } | 501 } |
| 503 return NULL; | 502 return nullptr; |
| 504 } | 503 } |
| 505 | 504 |
| 506 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( | 505 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( |
| 507 int session_id, | 506 int session_id, |
| 508 const ControllerClients& clients) { | 507 const ControllerClients& clients) { |
| 509 for (auto* client : clients) { | 508 for (const auto& client : clients) { |
| 510 if (client->session_id == session_id) | 509 if (client->session_id == session_id) |
| 511 return client; | 510 return client.get(); |
| 512 } | 511 } |
| 513 return NULL; | 512 return nullptr; |
| 514 } | 513 } |
| 515 | 514 |
| 516 } // namespace content | 515 } // namespace content |
| OLD | NEW |