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 <map> | 7 #include <map> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/metrics/sparse_histogram.h" | 13 #include "base/metrics/sparse_histogram.h" |
| 14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 15 #include "content/browser/renderer_host/media/media_stream_manager.h" | 15 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 16 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" | 16 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" |
| 17 #include "content/browser/renderer_host/media/video_capture_device_client.h" | 17 #include "content/browser/renderer_host/media/video_capture_device_client.h" |
| 18 #include "content/browser/renderer_host/media/video_capture_manager.h" | 18 #include "content/browser/renderer_host/media/video_capture_manager.h" |
| 19 #include "content/common/gpu/client/gl_helper.h" | 19 #include "content/common/gpu/client/gl_helper.h" |
| 20 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
| 21 #include "content/public/common/content_switches.h" | 21 #include "content/public/common/content_switches.h" |
| 22 #include "gpu/command_buffer/common/mailbox_holder.h" | |
| 23 #include "media/base/video_frame.h" | 22 #include "media/base/video_frame.h" |
| 24 | 23 |
| 25 #if !defined(OS_ANDROID) | 24 #if !defined(OS_ANDROID) |
| 26 #include "content/browser/compositor/image_transport_factory.h" | 25 #include "content/browser/compositor/image_transport_factory.h" |
| 27 #endif | 26 #endif |
| 28 | 27 |
| 29 using media::VideoCaptureFormat; | 28 using media::VideoCaptureFormat; |
| 30 using media::VideoFrame; | 29 using media::VideoFrame; |
| 31 using media::VideoFrameMetadata; | 30 using media::VideoFrameMetadata; |
| 32 | 31 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 147 | 146 |
| 148 void VideoCaptureController::AddClient( | 147 void VideoCaptureController::AddClient( |
| 149 VideoCaptureControllerID id, | 148 VideoCaptureControllerID id, |
| 150 VideoCaptureControllerEventHandler* event_handler, | 149 VideoCaptureControllerEventHandler* event_handler, |
| 151 base::ProcessHandle render_process, | 150 base::ProcessHandle render_process, |
| 152 media::VideoCaptureSessionId session_id, | 151 media::VideoCaptureSessionId session_id, |
| 153 const media::VideoCaptureParams& params) { | 152 const media::VideoCaptureParams& params) { |
| 154 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 153 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 155 DVLOG(1) << "VideoCaptureController::AddClient, id " << id | 154 DVLOG(1) << "VideoCaptureController::AddClient, id " << id |
| 156 << ", " << params.requested_format.frame_size.ToString() | 155 << ", " << params.requested_format.frame_size.ToString() |
| 157 << ", " << params.requested_format.frame_rate | 156 << ", " << params.requested_format.frame_rate |
|
mcasas
2015/11/17 02:23:47
Nit: Same as below, consider
media::VideoCaptureFo
miu
2015/11/17 04:28:02
Done.
| |
| 158 << ", " << session_id | 157 << ", " << session_id |
| 159 << ")"; | 158 << ")"; |
| 160 | 159 |
| 160 // Check that requested VideoCaptureParams are valid and supported. If not, | |
| 161 // report an error immediately and punt. | |
| 162 if (!params.IsValid() || | |
| 163 params.requested_format.pixel_format != media::PIXEL_FORMAT_I420 || | |
| 164 (params.requested_format.pixel_storage != media::PIXEL_STORAGE_CPU && | |
| 165 params.requested_format.pixel_storage != | |
| 166 media::PIXEL_STORAGE_GPUMEMORYBUFFER)) { | |
| 167 // Crash in debug builds since the renderer should not have asked for | |
| 168 // invalid or unsupported parameters. | |
| 169 LOG(DFATAL) << "Invalid or unsupported video capture parameters requested: " | |
| 170 << "frame_size=" | |
| 171 << params.requested_format.frame_size.ToString() | |
| 172 << ", frame_rate=" << params.requested_format.frame_rate | |
| 173 << ", pixel_format=" << media::VideoPixelFormatToString( | |
| 174 params.requested_format.pixel_format) | |
| 175 << ", pixel_storage=" << params.requested_format.pixel_storage; | |
|
mcasas
2015/11/17 02:23:47
Nit: Consider using [1]
media::VideoCaptureFormat
miu
2015/11/17 04:28:02
Done.
| |
| 176 event_handler->OnError(id); | |
| 177 return; | |
| 178 } | |
| 179 | |
| 161 // If this is the first client added to the controller, cache the parameters. | 180 // If this is the first client added to the controller, cache the parameters. |
| 162 if (!controller_clients_.size()) | 181 if (!controller_clients_.size()) |
| 163 video_capture_format_ = params.requested_format; | 182 video_capture_format_ = params.requested_format; |
| 164 | 183 |
| 165 // Signal error in case device is already in error state. | 184 // Signal error in case device is already in error state. |
| 166 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { | 185 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { |
| 167 event_handler->OnError(id); | 186 event_handler->OnError(id); |
| 168 return; | 187 return; |
| 169 } | 188 } |
| 170 | 189 |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 | 355 |
| 337 int count = 0; | 356 int count = 0; |
| 338 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 357 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
| 339 if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) { | 358 if (!frame->metadata()->HasKey(VideoFrameMetadata::FRAME_RATE)) { |
| 340 frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE, | 359 frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE, |
| 341 video_capture_format_.frame_rate); | 360 video_capture_format_.frame_rate); |
| 342 } | 361 } |
| 343 scoped_ptr<base::DictionaryValue> metadata(new base::DictionaryValue()); | 362 scoped_ptr<base::DictionaryValue> metadata(new base::DictionaryValue()); |
| 344 frame->metadata()->MergeInternalValuesInto(metadata.get()); | 363 frame->metadata()->MergeInternalValuesInto(metadata.get()); |
| 345 | 364 |
| 346 DCHECK( | 365 // Only I420 pixel format is currently supported. |
| 347 (frame->IsMappable() && frame->format() == media::PIXEL_FORMAT_I420) || | 366 DCHECK_EQ(frame->format(), media::PIXEL_FORMAT_I420) |
| 348 (frame->HasTextures() && frame->format() == media::PIXEL_FORMAT_ARGB)) | 367 << "Unsupported pixel format: " |
| 349 << "Format and/or storage type combination not supported (received: " | 368 << media::VideoPixelFormatToString(frame->format()); |
| 350 << media::VideoPixelFormatToString(frame->format()) << ")"; | 369 |
| 370 // Sanity-checks to confirm |frame| is actually being backed by |buffer|. | |
| 371 DCHECK(frame->storage_type() == media::VideoFrame::STORAGE_SHMEM || | |
| 372 (frame->storage_type() == | |
| 373 media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS)); | |
| 374 DCHECK(frame->data(media::VideoFrame::kYPlane) >= buffer->data(0) && | |
| 375 (frame->data(media::VideoFrame::kYPlane) < | |
| 376 (reinterpret_cast<const uint8*>(buffer->data(0)) + | |
| 377 buffer->mapped_size()))) | |
| 378 << "VideoFrame does not appear to be backed by Buffer"; | |
| 351 | 379 |
| 352 for (const auto& client : controller_clients_) { | 380 for (const auto& client : controller_clients_) { |
| 353 if (client->session_closed || client->paused) | 381 if (client->session_closed || client->paused) |
| 354 continue; | 382 continue; |
| 355 | 383 |
| 356 // On the first use of a buffer on a client, share the memory handles. | 384 // On the first use of a buffer on a client, share the memory handles. |
| 357 const bool is_new_buffer = client->known_buffers.insert(buffer_id).second; | 385 const bool is_new_buffer = client->known_buffers.insert(buffer_id).second; |
| 358 if (is_new_buffer) | 386 if (is_new_buffer) |
| 359 DoNewBufferOnIOThread(client, buffer.get(), frame); | 387 DoNewBufferOnIOThread(client, buffer.get(), frame); |
| 360 | 388 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 } | 449 } |
| 422 } | 450 } |
| 423 | 451 |
| 424 void VideoCaptureController::DoNewBufferOnIOThread( | 452 void VideoCaptureController::DoNewBufferOnIOThread( |
| 425 ControllerClient* client, | 453 ControllerClient* client, |
| 426 media::VideoCaptureDevice::Client::Buffer* buffer, | 454 media::VideoCaptureDevice::Client::Buffer* buffer, |
| 427 const scoped_refptr<media::VideoFrame>& frame) { | 455 const scoped_refptr<media::VideoFrame>& frame) { |
| 428 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 456 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 429 const int buffer_id = buffer->id(); | 457 const int buffer_id = buffer->id(); |
| 430 | 458 |
| 431 if (frame->HasTextures()) { | 459 switch (frame->storage_type()) { |
| 432 DCHECK_EQ(frame->format(), media::PIXEL_FORMAT_ARGB); | 460 case media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS: { |
| 433 DCHECK(frame->coded_size() == frame->visible_rect().size()) | 461 std::vector<gfx::GpuMemoryBufferHandle> handles; |
| 434 << "Textures shouldn't be crop-marked or letterboxed."; | 462 const size_t num_planes = media::VideoFrame::NumPlanes(frame->format()); |
| 435 return; | 463 for (size_t i = 0; i < num_planes; ++i) { |
| 436 } | 464 gfx::GpuMemoryBufferHandle remote_handle; |
| 437 | 465 buffer_pool_->ShareToProcess2( |
| 438 DCHECK_EQ(frame->format(), media::PIXEL_FORMAT_I420); | 466 buffer_id, i, client->render_process_handle, &remote_handle); |
| 439 if (frame->storage_type() == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS) { | 467 handles.push_back(remote_handle); |
| 440 std::vector<gfx::GpuMemoryBufferHandle> handles; | 468 } |
| 441 for (size_t i = 0; i < media::VideoFrame::NumPlanes(frame->format()); ++i) { | 469 client->event_handler->OnBufferCreated2(client->controller_id, handles, |
| 442 gfx::GpuMemoryBufferHandle remote_handle; | 470 buffer->dimensions(), buffer_id); |
| 443 buffer_pool_->ShareToProcess2(buffer_id, i, client->render_process_handle, | 471 break; |
| 444 &remote_handle); | |
| 445 handles.push_back(remote_handle); | |
| 446 } | 472 } |
| 447 client->event_handler->OnBufferCreated2(client->controller_id, handles, | 473 case media::VideoFrame::STORAGE_SHMEM: { |
| 448 buffer->dimensions(), buffer_id); | 474 base::SharedMemoryHandle remote_handle; |
| 449 } else { | 475 buffer_pool_->ShareToProcess(buffer_id, client->render_process_handle, |
| 450 base::SharedMemoryHandle remote_handle; | 476 &remote_handle); |
| 451 buffer_pool_->ShareToProcess(buffer_id, client->render_process_handle, | 477 client->event_handler->OnBufferCreated( |
| 452 &remote_handle); | 478 client->controller_id, remote_handle, buffer->mapped_size(), |
| 453 | 479 buffer_id); |
| 454 client->event_handler->OnBufferCreated(client->controller_id, remote_handle, | 480 break; |
| 455 buffer->mapped_size(), buffer_id); | 481 } |
| 482 default: | |
| 483 NOTREACHED(); | |
| 484 break; | |
| 456 } | 485 } |
| 457 } | 486 } |
| 458 | 487 |
| 459 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( | 488 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( |
| 460 VideoCaptureControllerID id, | 489 VideoCaptureControllerID id, |
| 461 VideoCaptureControllerEventHandler* handler, | 490 VideoCaptureControllerEventHandler* handler, |
| 462 const ControllerClients& clients) { | 491 const ControllerClients& clients) { |
| 463 for (auto* client : clients) { | 492 for (auto* client : clients) { |
| 464 if (client->controller_id == id && client->event_handler == handler) | 493 if (client->controller_id == id && client->event_handler == handler) |
| 465 return client; | 494 return client; |
| 466 } | 495 } |
| 467 return NULL; | 496 return NULL; |
| 468 } | 497 } |
| 469 | 498 |
| 470 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( | 499 VideoCaptureController::ControllerClient* VideoCaptureController::FindClient( |
| 471 int session_id, | 500 int session_id, |
| 472 const ControllerClients& clients) { | 501 const ControllerClients& clients) { |
| 473 for (auto client : clients) { | 502 for (auto client : clients) { |
| 474 if (client->session_id == session_id) | 503 if (client->session_id == session_id) |
| 475 return client; | 504 return client; |
| 476 } | 505 } |
| 477 return NULL; | 506 return NULL; |
| 478 } | 507 } |
| 479 | 508 |
| 480 } // namespace content | 509 } // namespace content |
| OLD | NEW |