| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_device_client.h" | 5 #include "content/browser/renderer_host/media/video_capture_device_client.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "base/trace_event/trace_event.h" | 13 #include "base/trace_event/trace_event.h" |
| 14 #include "content/browser/compositor/image_transport_factory.h" | |
| 15 #include "content/browser/gpu/browser_gpu_channel_host_factory.h" | |
| 16 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" | |
| 17 #include "content/browser/gpu/gpu_data_manager_impl.h" | |
| 18 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" | 14 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" |
| 19 #include "content/browser/renderer_host/media/video_capture_controller.h" | 15 #include "content/browser/renderer_host/media/video_capture_controller.h" |
| 20 #include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h" | 16 #include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h" |
| 21 #include "content/common/gpu/client/context_provider_command_buffer.h" | |
| 22 #include "content/common/gpu/client/gl_helper.h" | |
| 23 #include "content/common/gpu/client/gpu_channel_host.h" | |
| 24 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" | |
| 25 #include "content/common/gpu/gpu_process_launch_causes.h" | |
| 26 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
| 27 #include "gpu/command_buffer/common/mailbox_holder.h" | |
| 28 #include "media/base/bind_to_current_loop.h" | 18 #include "media/base/bind_to_current_loop.h" |
| 29 #include "media/base/media_switches.h" | 19 #include "media/base/media_switches.h" |
| 30 #include "media/base/video_capture_types.h" | 20 #include "media/base/video_capture_types.h" |
| 31 #include "media/base/video_frame.h" | 21 #include "media/base/video_frame.h" |
| 32 #include "third_party/khronos/GLES2/gl2ext.h" | |
| 33 #include "third_party/libyuv/include/libyuv.h" | 22 #include "third_party/libyuv/include/libyuv.h" |
| 34 | 23 |
| 35 using media::VideoCaptureFormat; | 24 using media::VideoCaptureFormat; |
| 36 using media::VideoFrame; | 25 using media::VideoFrame; |
| 37 using media::VideoFrameMetadata; | 26 using media::VideoFrameMetadata; |
| 38 | 27 |
| 39 namespace content { | 28 namespace content { |
| 40 | 29 |
| 41 // Class combining a Client::Buffer interface implementation and a pool buffer | 30 // Class combining a Client::Buffer interface implementation and a pool buffer |
| 42 // implementation to guarantee proper cleanup on destruction on our side. | 31 // implementation to guarantee proper cleanup on destruction on our side. |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 } | 303 } |
| 315 | 304 |
| 316 OnIncomingCapturedBuffer(buffer.Pass(), frame_format, timestamp); | 305 OnIncomingCapturedBuffer(buffer.Pass(), frame_format, timestamp); |
| 317 }; | 306 }; |
| 318 | 307 |
| 319 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> | 308 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> |
| 320 VideoCaptureDeviceClient::ReserveOutputBuffer( | 309 VideoCaptureDeviceClient::ReserveOutputBuffer( |
| 321 const gfx::Size& frame_size, | 310 const gfx::Size& frame_size, |
| 322 media::VideoPixelFormat pixel_format, | 311 media::VideoPixelFormat pixel_format, |
| 323 media::VideoPixelStorage pixel_storage) { | 312 media::VideoPixelStorage pixel_storage) { |
| 324 DCHECK(pixel_format == media::PIXEL_FORMAT_I420 || | |
| 325 pixel_format == media::PIXEL_FORMAT_ARGB); | |
| 326 DCHECK_GT(frame_size.width(), 0); | 313 DCHECK_GT(frame_size.width(), 0); |
| 327 DCHECK_GT(frame_size.height(), 0); | 314 DCHECK_GT(frame_size.height(), 0); |
| 315 // Currently, only I420 pixel format is supported. |
| 316 DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format); |
| 328 | 317 |
| 329 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if | 318 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if |
| 330 // it's a ShMem GMB or a DmaBuf GMB. | 319 // it's a ShMem GMB or a DmaBuf GMB. |
| 331 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; | 320 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; |
| 332 const int buffer_id = buffer_pool_->ReserveForProducer( | 321 const int buffer_id = buffer_pool_->ReserveForProducer( |
| 333 pixel_format, pixel_storage, frame_size, &buffer_id_to_drop); | 322 pixel_format, pixel_storage, frame_size, &buffer_id_to_drop); |
| 334 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 323 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
| 335 return NULL; | 324 return NULL; |
| 336 | 325 |
| 337 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> output_buffer( | 326 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> output_buffer( |
| 338 new AutoReleaseBuffer(buffer_pool_, buffer_id)); | 327 new AutoReleaseBuffer(buffer_pool_, buffer_id)); |
| 339 | 328 |
| 340 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { | 329 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { |
| 341 BrowserThread::PostTask(BrowserThread::IO, | 330 BrowserThread::PostTask(BrowserThread::IO, |
| 342 FROM_HERE, | 331 FROM_HERE, |
| 343 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, | 332 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, |
| 344 controller_, buffer_id_to_drop)); | 333 controller_, buffer_id_to_drop)); |
| 345 } | 334 } |
| 346 | 335 |
| 347 return output_buffer.Pass(); | 336 return output_buffer.Pass(); |
| 348 } | 337 } |
| 349 | 338 |
| 350 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 339 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
| 351 scoped_ptr<Buffer> buffer, | 340 scoped_ptr<Buffer> buffer, |
| 352 const VideoCaptureFormat& frame_format, | 341 const VideoCaptureFormat& frame_format, |
| 353 const base::TimeTicks& timestamp) { | 342 const base::TimeTicks& timestamp) { |
| 354 DCHECK(frame_format.pixel_format == media::PIXEL_FORMAT_I420); | 343 // Currently, only I420 pixel format is supported. |
| 344 DCHECK_EQ(media::PIXEL_FORMAT_I420, frame_format.pixel_format); |
| 345 |
| 355 scoped_refptr<VideoFrame> frame; | 346 scoped_refptr<VideoFrame> frame; |
| 356 if (frame_format.pixel_storage == media::PIXEL_STORAGE_GPUMEMORYBUFFER) { | 347 switch (frame_format.pixel_storage) { |
| 357 // Create a VideoFrame to set the correct storage_type and pixel_format. | 348 case media::PIXEL_STORAGE_GPUMEMORYBUFFER: { |
| 358 gfx::GpuMemoryBufferHandle handle; | 349 // Create a VideoFrame to set the correct storage_type and pixel_format. |
| 359 frame = VideoFrame::WrapExternalYuvGpuMemoryBuffers( | 350 gfx::GpuMemoryBufferHandle handle; |
| 360 media::PIXEL_FORMAT_I420, frame_format.frame_size, | 351 frame = VideoFrame::WrapExternalYuvGpuMemoryBuffers( |
| 361 gfx::Rect(frame_format.frame_size), frame_format.frame_size, 0, 0, 0, | 352 media::PIXEL_FORMAT_I420, frame_format.frame_size, |
| 362 reinterpret_cast<uint8*>(buffer->data(media::VideoFrame::kYPlane)), | 353 gfx::Rect(frame_format.frame_size), frame_format.frame_size, 0, 0, 0, |
| 363 reinterpret_cast<uint8*>(buffer->data(media::VideoFrame::kUPlane)), | 354 reinterpret_cast<uint8*>(buffer->data(media::VideoFrame::kYPlane)), |
| 364 reinterpret_cast<uint8*>(buffer->data(media::VideoFrame::kVPlane)), | 355 reinterpret_cast<uint8*>(buffer->data(media::VideoFrame::kUPlane)), |
| 365 handle, handle, handle, base::TimeDelta()); | 356 reinterpret_cast<uint8*>(buffer->data(media::VideoFrame::kVPlane)), |
| 366 } else { | 357 handle, handle, handle, base::TimeDelta()); |
| 367 frame = VideoFrame::WrapExternalData( | 358 break; |
| 368 media::PIXEL_FORMAT_I420, frame_format.frame_size, | 359 } |
| 369 gfx::Rect(frame_format.frame_size), frame_format.frame_size, | 360 case media::PIXEL_STORAGE_CPU: |
| 370 reinterpret_cast<uint8*>(buffer->data()), | 361 frame = VideoFrame::WrapExternalSharedMemory( |
| 371 VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, | 362 media::PIXEL_FORMAT_I420, frame_format.frame_size, |
| 372 frame_format.frame_size), | 363 gfx::Rect(frame_format.frame_size), frame_format.frame_size, |
| 373 base::TimeDelta()); | 364 reinterpret_cast<uint8*>(buffer->data()), |
| 365 VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, |
| 366 frame_format.frame_size), |
| 367 base::SharedMemory::NULLHandle(), 0u, base::TimeDelta()); |
| 368 break; |
| 374 } | 369 } |
| 375 DCHECK(frame.get()); | 370 DCHECK(frame.get()); |
| 376 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, | 371 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
| 377 frame_format.frame_rate); | 372 frame_format.frame_rate); |
| 378 OnIncomingCapturedVideoFrame(buffer.Pass(), frame, timestamp); | 373 OnIncomingCapturedVideoFrame(buffer.Pass(), frame, timestamp); |
| 379 } | 374 } |
| 380 | 375 |
| 381 void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( | 376 void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( |
| 382 scoped_ptr<Buffer> buffer, | 377 scoped_ptr<Buffer> buffer, |
| 383 const scoped_refptr<VideoFrame>& frame, | 378 const scoped_refptr<VideoFrame>& frame, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 storage == media::PIXEL_STORAGE_CPU); | 426 storage == media::PIXEL_STORAGE_CPU); |
| 432 DCHECK(dimensions.height()); | 427 DCHECK(dimensions.height()); |
| 433 DCHECK(dimensions.width()); | 428 DCHECK(dimensions.width()); |
| 434 | 429 |
| 435 const media::VideoPixelFormat format = media::PIXEL_FORMAT_I420; | 430 const media::VideoPixelFormat format = media::PIXEL_FORMAT_I420; |
| 436 scoped_ptr<Buffer> buffer(ReserveOutputBuffer( | 431 scoped_ptr<Buffer> buffer(ReserveOutputBuffer( |
| 437 dimensions, media::PIXEL_FORMAT_I420, storage)); | 432 dimensions, media::PIXEL_FORMAT_I420, storage)); |
| 438 if (!buffer) | 433 if (!buffer) |
| 439 return scoped_ptr<Buffer>(); | 434 return scoped_ptr<Buffer>(); |
| 440 | 435 |
| 441 if (storage == media::PIXEL_STORAGE_CPU) { | 436 switch (storage) { |
| 442 // TODO(emircan): See http://crbug.com/521068, move this pointer arithmetic | 437 case media::PIXEL_STORAGE_CPU: |
| 443 // inside Buffer::data() when this bug is resolved. | 438 // TODO(emircan): See http://crbug.com/521068, move this pointer |
| 444 *y_plane_data = reinterpret_cast<uint8*>(buffer->data()); | 439 // arithmetic inside Buffer::data() when this bug is resolved. |
| 445 *u_plane_data = | 440 *y_plane_data = reinterpret_cast<uint8*>(buffer->data()); |
| 446 *y_plane_data + | 441 *u_plane_data = |
| 447 VideoFrame::PlaneSize(format, VideoFrame::kYPlane, dimensions) | 442 *y_plane_data + |
| 448 .GetArea(); | 443 VideoFrame::PlaneSize(format, VideoFrame::kYPlane, dimensions) |
| 449 *v_plane_data = | 444 .GetArea(); |
| 450 *u_plane_data + | 445 *v_plane_data = |
| 451 VideoFrame::PlaneSize(format, VideoFrame::kUPlane, dimensions) | 446 *u_plane_data + |
| 452 .GetArea(); | 447 VideoFrame::PlaneSize(format, VideoFrame::kUPlane, dimensions) |
| 453 } else if (storage == media::PIXEL_STORAGE_GPUMEMORYBUFFER) { | 448 .GetArea(); |
| 454 *y_plane_data = reinterpret_cast<uint8*>(buffer->data(VideoFrame::kYPlane)); | 449 return buffer.Pass(); |
| 455 *u_plane_data = reinterpret_cast<uint8*>(buffer->data(VideoFrame::kUPlane)); | 450 case media::PIXEL_STORAGE_GPUMEMORYBUFFER: |
| 456 *v_plane_data = reinterpret_cast<uint8*>(buffer->data(VideoFrame::kVPlane)); | 451 *y_plane_data = |
| 452 reinterpret_cast<uint8*>(buffer->data(VideoFrame::kYPlane)); |
| 453 *u_plane_data = |
| 454 reinterpret_cast<uint8*>(buffer->data(VideoFrame::kUPlane)); |
| 455 *v_plane_data = |
| 456 reinterpret_cast<uint8*>(buffer->data(VideoFrame::kVPlane)); |
| 457 return buffer.Pass(); |
| 457 } | 458 } |
| 458 return buffer.Pass(); | 459 NOTREACHED(); |
| 460 return scoped_ptr<Buffer>(); |
| 459 } | 461 } |
| 460 | 462 |
| 461 } // namespace content | 463 } // namespace content |
| OLD | NEW |