| 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 "media/capture/video/video_capture_device_client.h" | 5 #include "media/capture/video/video_capture_device_client.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 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/location.h" | 12 #include "base/location.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 15 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 17 #include "media/base/bind_to_current_loop.h" | 17 #include "media/base/bind_to_current_loop.h" |
| 18 #include "media/base/media_switches.h" | |
| 19 #include "media/base/video_capture_types.h" | 18 #include "media/base/video_capture_types.h" |
| 20 #include "media/base/video_frame.h" | 19 #include "media/base/video_frame.h" |
| 21 #include "media/capture/video/video_capture_buffer_handle.h" | 20 #include "media/capture/video/video_capture_buffer_handle.h" |
| 22 #include "media/capture/video/video_capture_buffer_pool.h" | 21 #include "media/capture/video/video_capture_buffer_pool.h" |
| 23 #include "media/capture/video/video_capture_jpeg_decoder.h" | 22 #include "media/capture/video/video_capture_jpeg_decoder.h" |
| 24 #include "media/capture/video/video_frame_receiver.h" | 23 #include "media/capture/video/video_frame_receiver.h" |
| 25 #include "third_party/libyuv/include/libyuv.h" | 24 #include "third_party/libyuv/include/libyuv.h" |
| 26 | 25 |
| 27 using media::VideoCaptureFormat; | 26 using media::VideoCaptureFormat; |
| 28 using media::VideoFrame; | 27 using media::VideoFrame; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 }; | 62 }; |
| 64 | 63 |
| 65 VideoCaptureDeviceClient::VideoCaptureDeviceClient( | 64 VideoCaptureDeviceClient::VideoCaptureDeviceClient( |
| 66 std::unique_ptr<VideoFrameReceiver> receiver, | 65 std::unique_ptr<VideoFrameReceiver> receiver, |
| 67 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool, | 66 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool, |
| 68 const VideoCaptureJpegDecoderFactoryCB& jpeg_decoder_factory) | 67 const VideoCaptureJpegDecoderFactoryCB& jpeg_decoder_factory) |
| 69 : receiver_(std::move(receiver)), | 68 : receiver_(std::move(receiver)), |
| 70 jpeg_decoder_factory_callback_(jpeg_decoder_factory), | 69 jpeg_decoder_factory_callback_(jpeg_decoder_factory), |
| 71 external_jpeg_decoder_initialized_(false), | 70 external_jpeg_decoder_initialized_(false), |
| 72 buffer_pool_(buffer_pool), | 71 buffer_pool_(buffer_pool), |
| 73 use_gpu_memory_buffers_(base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 74 switches::kUseGpuMemoryBuffersForCapture)), | |
| 75 last_captured_pixel_format_(media::PIXEL_FORMAT_UNKNOWN) {} | 72 last_captured_pixel_format_(media::PIXEL_FORMAT_UNKNOWN) {} |
| 76 | 73 |
| 77 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() { | 74 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() { |
| 78 // This should be on the platform auxiliary thread since | 75 // This should be on the platform auxiliary thread since |
| 79 // |external_jpeg_decoder_| need to be destructed on the same thread as | 76 // |external_jpeg_decoder_| need to be destructed on the same thread as |
| 80 // OnIncomingCapturedData. | 77 // OnIncomingCapturedData. |
| 81 } | 78 } |
| 82 | 79 |
| 83 void VideoCaptureDeviceClient::OnIncomingCapturedData( | 80 void VideoCaptureDeviceClient::OnIncomingCapturedData( |
| 84 const uint8_t* data, | 81 const uint8_t* data, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 << rotation; | 119 << rotation; |
| 123 libyuv::RotationMode rotation_mode = libyuv::kRotate0; | 120 libyuv::RotationMode rotation_mode = libyuv::kRotate0; |
| 124 if (rotation == 90) | 121 if (rotation == 90) |
| 125 rotation_mode = libyuv::kRotate90; | 122 rotation_mode = libyuv::kRotate90; |
| 126 else if (rotation == 180) | 123 else if (rotation == 180) |
| 127 rotation_mode = libyuv::kRotate180; | 124 rotation_mode = libyuv::kRotate180; |
| 128 else if (rotation == 270) | 125 else if (rotation == 270) |
| 129 rotation_mode = libyuv::kRotate270; | 126 rotation_mode = libyuv::kRotate270; |
| 130 | 127 |
| 131 const gfx::Size dimensions(destination_width, destination_height); | 128 const gfx::Size dimensions(destination_width, destination_height); |
| 132 const media::VideoPixelStorage output_pixel_storage = | |
| 133 use_gpu_memory_buffers_ ? media::PIXEL_STORAGE_GPUMEMORYBUFFER | |
| 134 : media::PIXEL_STORAGE_CPU; | |
| 135 uint8_t *y_plane_data, *u_plane_data, *v_plane_data; | 129 uint8_t *y_plane_data, *u_plane_data, *v_plane_data; |
| 136 std::unique_ptr<Buffer> buffer( | 130 std::unique_ptr<Buffer> buffer( |
| 137 ReserveI420OutputBuffer(dimensions, output_pixel_storage, &y_plane_data, | 131 ReserveI420OutputBuffer(dimensions, media::PIXEL_STORAGE_CPU, |
| 138 &u_plane_data, &v_plane_data)); | 132 &y_plane_data, &u_plane_data, &v_plane_data)); |
| 139 #if DCHECK_IS_ON() | 133 #if DCHECK_IS_ON() |
| 140 dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; | 134 dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; |
| 141 if (dropped_frame_counter_ >= kMaxDroppedFrames) | 135 if (dropped_frame_counter_ >= kMaxDroppedFrames) |
| 142 OnError(FROM_HERE, "Too many frames dropped"); | 136 OnError(FROM_HERE, "Too many frames dropped"); |
| 143 #endif | 137 #endif |
| 144 // Failed to reserve I420 output buffer, so drop the frame. | 138 // Failed to reserve I420 output buffer, so drop the frame. |
| 145 if (!buffer.get()) | 139 if (!buffer.get()) |
| 146 return; | 140 return; |
| 147 | 141 |
| 148 const int yplane_stride = dimensions.width(); | 142 const int yplane_stride = dimensions.width(); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 (flip ? -1 : 1) * frame_format.frame_size.height(), | 235 (flip ? -1 : 1) * frame_format.frame_size.height(), |
| 242 new_unrotated_width, new_unrotated_height, | 236 new_unrotated_width, new_unrotated_height, |
| 243 rotation_mode, origin_colorspace) != 0) { | 237 rotation_mode, origin_colorspace) != 0) { |
| 244 DLOG(WARNING) << "Failed to convert buffer's pixel format to I420 from " | 238 DLOG(WARNING) << "Failed to convert buffer's pixel format to I420 from " |
| 245 << media::VideoPixelFormatToString(frame_format.pixel_format); | 239 << media::VideoPixelFormatToString(frame_format.pixel_format); |
| 246 return; | 240 return; |
| 247 } | 241 } |
| 248 | 242 |
| 249 const VideoCaptureFormat output_format = | 243 const VideoCaptureFormat output_format = |
| 250 VideoCaptureFormat(dimensions, frame_format.frame_rate, | 244 VideoCaptureFormat(dimensions, frame_format.frame_rate, |
| 251 media::PIXEL_FORMAT_I420, output_pixel_storage); | 245 media::PIXEL_FORMAT_I420, media::PIXEL_STORAGE_CPU); |
| 252 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, | 246 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, |
| 253 timestamp); | 247 timestamp); |
| 254 } | 248 } |
| 255 | 249 |
| 256 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 250 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
| 257 VideoCaptureDeviceClient::ReserveOutputBuffer( | 251 VideoCaptureDeviceClient::ReserveOutputBuffer( |
| 258 const gfx::Size& frame_size, | 252 const gfx::Size& frame_size, |
| 259 media::VideoPixelFormat pixel_format, | 253 media::VideoPixelFormat pixel_format, |
| 260 media::VideoPixelStorage pixel_storage) { | 254 media::VideoPixelStorage pixel_storage) { |
| 261 DCHECK_GT(frame_size.width(), 0); | 255 DCHECK_GT(frame_size.width(), 0); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 276 new AutoReleaseBuffer(buffer_pool_, buffer_id)); | 270 new AutoReleaseBuffer(buffer_pool_, buffer_id)); |
| 277 } | 271 } |
| 278 | 272 |
| 279 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 273 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
| 280 std::unique_ptr<Buffer> buffer, | 274 std::unique_ptr<Buffer> buffer, |
| 281 const VideoCaptureFormat& frame_format, | 275 const VideoCaptureFormat& frame_format, |
| 282 base::TimeTicks reference_time, | 276 base::TimeTicks reference_time, |
| 283 base::TimeDelta timestamp) { | 277 base::TimeDelta timestamp) { |
| 284 // Currently, only I420 pixel format is supported. | 278 // Currently, only I420 pixel format is supported. |
| 285 DCHECK_EQ(media::PIXEL_FORMAT_I420, frame_format.pixel_format); | 279 DCHECK_EQ(media::PIXEL_FORMAT_I420, frame_format.pixel_format); |
| 280 DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage); |
| 286 | 281 |
| 287 scoped_refptr<VideoFrame> frame; | 282 scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory( |
| 288 switch (frame_format.pixel_storage) { | 283 media::PIXEL_FORMAT_I420, frame_format.frame_size, |
| 289 case media::PIXEL_STORAGE_GPUMEMORYBUFFER: { | 284 gfx::Rect(frame_format.frame_size), frame_format.frame_size, |
| 290 // Create a VideoFrame to set the correct storage_type and pixel_format. | 285 reinterpret_cast<uint8_t*>(buffer->data()), |
| 291 gfx::GpuMemoryBufferHandle handle; | 286 VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, |
| 292 frame = VideoFrame::WrapExternalYuvGpuMemoryBuffers( | 287 frame_format.frame_size), |
| 293 media::PIXEL_FORMAT_I420, frame_format.frame_size, | 288 base::SharedMemory::NULLHandle(), 0u, timestamp); |
| 294 gfx::Rect(frame_format.frame_size), frame_format.frame_size, 0, 0, 0, | |
| 295 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kYPlane)), | |
| 296 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kUPlane)), | |
| 297 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kVPlane)), | |
| 298 handle, handle, handle, timestamp); | |
| 299 break; | |
| 300 } | |
| 301 case media::PIXEL_STORAGE_CPU: | |
| 302 frame = VideoFrame::WrapExternalSharedMemory( | |
| 303 media::PIXEL_FORMAT_I420, frame_format.frame_size, | |
| 304 gfx::Rect(frame_format.frame_size), frame_format.frame_size, | |
| 305 reinterpret_cast<uint8_t*>(buffer->data()), | |
| 306 VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, | |
| 307 frame_format.frame_size), | |
| 308 base::SharedMemory::NULLHandle(), 0u, timestamp); | |
| 309 break; | |
| 310 } | |
| 311 if (!frame) | 289 if (!frame) |
| 312 return; | 290 return; |
| 313 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, | 291 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
| 314 frame_format.frame_rate); | 292 frame_format.frame_rate); |
| 315 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, | 293 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, |
| 316 reference_time); | 294 reference_time); |
| 317 OnIncomingCapturedVideoFrame(std::move(buffer), frame); | 295 OnIncomingCapturedVideoFrame(std::move(buffer), frame); |
| 318 } | 296 } |
| 319 | 297 |
| 320 void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( | 298 void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 return buffer_pool_->GetBufferPoolUtilization(); | 335 return buffer_pool_->GetBufferPoolUtilization(); |
| 358 } | 336 } |
| 359 | 337 |
| 360 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 338 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
| 361 VideoCaptureDeviceClient::ReserveI420OutputBuffer( | 339 VideoCaptureDeviceClient::ReserveI420OutputBuffer( |
| 362 const gfx::Size& dimensions, | 340 const gfx::Size& dimensions, |
| 363 media::VideoPixelStorage storage, | 341 media::VideoPixelStorage storage, |
| 364 uint8_t** y_plane_data, | 342 uint8_t** y_plane_data, |
| 365 uint8_t** u_plane_data, | 343 uint8_t** u_plane_data, |
| 366 uint8_t** v_plane_data) { | 344 uint8_t** v_plane_data) { |
| 367 DCHECK(storage == media::PIXEL_STORAGE_GPUMEMORYBUFFER || | 345 DCHECK(storage == media::PIXEL_STORAGE_CPU); |
| 368 storage == media::PIXEL_STORAGE_CPU); | |
| 369 DCHECK(dimensions.height()); | 346 DCHECK(dimensions.height()); |
| 370 DCHECK(dimensions.width()); | 347 DCHECK(dimensions.width()); |
| 371 | 348 |
| 372 const media::VideoPixelFormat format = media::PIXEL_FORMAT_I420; | 349 const media::VideoPixelFormat format = media::PIXEL_FORMAT_I420; |
| 373 std::unique_ptr<Buffer> buffer( | 350 std::unique_ptr<Buffer> buffer( |
| 374 ReserveOutputBuffer(dimensions, media::PIXEL_FORMAT_I420, storage)); | 351 ReserveOutputBuffer(dimensions, media::PIXEL_FORMAT_I420, storage)); |
| 375 if (!buffer) | 352 if (!buffer) |
| 376 return std::unique_ptr<Buffer>(); | 353 return std::unique_ptr<Buffer>(); |
| 377 | 354 // TODO(emircan): See http://crbug.com/521068, move this pointer |
| 378 switch (storage) { | 355 // arithmetic inside Buffer::data() when this bug is resolved. |
| 379 case media::PIXEL_STORAGE_CPU: | 356 *y_plane_data = reinterpret_cast<uint8_t*>(buffer->data()); |
| 380 // TODO(emircan): See http://crbug.com/521068, move this pointer | 357 *u_plane_data = |
| 381 // arithmetic inside Buffer::data() when this bug is resolved. | 358 *y_plane_data + |
| 382 *y_plane_data = reinterpret_cast<uint8_t*>(buffer->data()); | 359 VideoFrame::PlaneSize(format, VideoFrame::kYPlane, dimensions).GetArea(); |
| 383 *u_plane_data = | 360 *v_plane_data = |
| 384 *y_plane_data + | 361 *u_plane_data + |
| 385 VideoFrame::PlaneSize(format, VideoFrame::kYPlane, dimensions) | 362 VideoFrame::PlaneSize(format, VideoFrame::kUPlane, dimensions).GetArea(); |
| 386 .GetArea(); | 363 return buffer; |
| 387 *v_plane_data = | |
| 388 *u_plane_data + | |
| 389 VideoFrame::PlaneSize(format, VideoFrame::kUPlane, dimensions) | |
| 390 .GetArea(); | |
| 391 return buffer; | |
| 392 case media::PIXEL_STORAGE_GPUMEMORYBUFFER: | |
| 393 *y_plane_data = | |
| 394 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kYPlane)); | |
| 395 *u_plane_data = | |
| 396 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kUPlane)); | |
| 397 *v_plane_data = | |
| 398 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kVPlane)); | |
| 399 return buffer; | |
| 400 } | |
| 401 NOTREACHED(); | |
| 402 return std::unique_ptr<Buffer>(); | |
| 403 } | 364 } |
| 404 | 365 |
| 405 } // namespace media | 366 } // namespace media |
| OLD | NEW |