Chromium Code Reviews| 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/video_frame.h" | 18 #include "media/base/video_frame.h" |
| 19 #include "media/capture/video/video_capture_buffer_handle.h" | 19 #include "media/capture/video/video_capture_buffer_handle.h" |
| 20 #include "media/capture/video/video_capture_buffer_pool.h" | 20 #include "media/capture/video/video_capture_buffer_pool.h" |
| 21 #include "media/capture/video/video_capture_jpeg_decoder.h" | 21 #include "media/capture/video/video_capture_jpeg_decoder.h" |
| 22 #include "media/capture/video/video_frame_receiver.h" | 22 #include "media/capture/video/video_frame_receiver.h" |
| 23 #include "media/capture/video_capture_types.h" | 23 #include "media/capture/video_capture_types.h" |
| 24 #include "third_party/libyuv/include/libyuv.h" | 24 #include "third_party/libyuv/include/libyuv.h" |
| 25 | 25 |
| 26 using media::VideoCaptureFormat; | 26 using media::VideoCaptureFormat; |
| 27 using media::VideoFrame; | 27 using media::VideoFrame; |
| 28 using media::VideoFrameMetadata; | 28 using media::VideoFrameMetadata; |
| 29 | 29 |
| 30 namespace { | |
| 31 | |
| 32 bool IsFormatSupported(media::VideoPixelFormat pixel_format) { | |
| 33 return (pixel_format == media::PIXEL_FORMAT_I420 || | |
| 34 pixel_format == media::PIXEL_FORMAT_Y16); | |
| 35 } | |
| 36 } | |
| 37 | |
| 30 namespace media { | 38 namespace media { |
| 31 | 39 |
| 32 // Class combining a Client::Buffer interface implementation and a pool buffer | 40 // Class combining a Client::Buffer interface implementation and a pool buffer |
| 33 // implementation to guarantee proper cleanup on destruction on our side. | 41 // implementation to guarantee proper cleanup on destruction on our side. |
| 34 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { | 42 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { |
| 35 public: | 43 public: |
| 36 AutoReleaseBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, | 44 AutoReleaseBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, |
| 37 int buffer_id) | 45 int buffer_id) |
| 38 : id_(buffer_id), | 46 : id_(buffer_id), |
| 39 pool_(pool), | 47 pool_(pool), |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 !external_jpeg_decoder_initialized_) { | 107 !external_jpeg_decoder_initialized_) { |
| 100 external_jpeg_decoder_initialized_ = true; | 108 external_jpeg_decoder_initialized_ = true; |
| 101 external_jpeg_decoder_ = jpeg_decoder_factory_callback_.Run(); | 109 external_jpeg_decoder_ = jpeg_decoder_factory_callback_.Run(); |
| 102 external_jpeg_decoder_->Initialize(); | 110 external_jpeg_decoder_->Initialize(); |
| 103 } | 111 } |
| 104 } | 112 } |
| 105 | 113 |
| 106 if (!frame_format.IsValid()) | 114 if (!frame_format.IsValid()) |
| 107 return; | 115 return; |
| 108 | 116 |
| 117 if (frame_format.pixel_format == media::PIXEL_FORMAT_Y16) | |
|
aleksandar.stojiljkovic
2016/10/28 18:58:55
mcasas@:
Online review: {} for bodies > 1 line.
D
| |
| 118 return OnIncomingCapturedY16Data(data, length, frame_format, reference_time, | |
| 119 timestamp); | |
| 120 | |
| 109 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest | 121 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest |
| 110 // bit decomposition of {width, height}, grabbing the odd and even parts. | 122 // bit decomposition of {width, height}, grabbing the odd and even parts. |
| 111 const int chopped_width = frame_format.frame_size.width() & 1; | 123 const int chopped_width = frame_format.frame_size.width() & 1; |
| 112 const int chopped_height = frame_format.frame_size.height() & 1; | 124 const int chopped_height = frame_format.frame_size.height() & 1; |
| 113 const int new_unrotated_width = frame_format.frame_size.width() & ~1; | 125 const int new_unrotated_width = frame_format.frame_size.width() & ~1; |
| 114 const int new_unrotated_height = frame_format.frame_size.height() & ~1; | 126 const int new_unrotated_height = frame_format.frame_size.height() & ~1; |
| 115 | 127 |
| 116 int destination_width = new_unrotated_width; | 128 int destination_width = new_unrotated_width; |
| 117 int destination_height = new_unrotated_height; | 129 int destination_height = new_unrotated_height; |
| 118 if (rotation == 90 || rotation == 270) | 130 if (rotation == 90 || rotation == 270) |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 timestamp); | 262 timestamp); |
| 251 } | 263 } |
| 252 | 264 |
| 253 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 265 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
| 254 VideoCaptureDeviceClient::ReserveOutputBuffer( | 266 VideoCaptureDeviceClient::ReserveOutputBuffer( |
| 255 const gfx::Size& frame_size, | 267 const gfx::Size& frame_size, |
| 256 media::VideoPixelFormat pixel_format, | 268 media::VideoPixelFormat pixel_format, |
| 257 media::VideoPixelStorage pixel_storage) { | 269 media::VideoPixelStorage pixel_storage) { |
| 258 DCHECK_GT(frame_size.width(), 0); | 270 DCHECK_GT(frame_size.width(), 0); |
| 259 DCHECK_GT(frame_size.height(), 0); | 271 DCHECK_GT(frame_size.height(), 0); |
| 260 // Currently, only I420 pixel format is supported. | 272 DCHECK(IsFormatSupported(pixel_format)); |
| 261 DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format); | |
| 262 | 273 |
| 263 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if | 274 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if |
| 264 // it's a ShMem GMB or a DmaBuf GMB. | 275 // it's a ShMem GMB or a DmaBuf GMB. |
| 265 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; | 276 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; |
| 266 const int buffer_id = buffer_pool_->ReserveForProducer( | 277 const int buffer_id = buffer_pool_->ReserveForProducer( |
| 267 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop); | 278 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop); |
| 268 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) | 279 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) |
| 269 receiver_->OnBufferDestroyed(buffer_id_to_drop); | 280 receiver_->OnBufferDestroyed(buffer_id_to_drop); |
| 270 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 281 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
| 271 return nullptr; | 282 return nullptr; |
| 272 return base::WrapUnique<Buffer>( | 283 return base::WrapUnique<Buffer>( |
| 273 new AutoReleaseBuffer(buffer_pool_, buffer_id)); | 284 new AutoReleaseBuffer(buffer_pool_, buffer_id)); |
| 274 } | 285 } |
| 275 | 286 |
| 276 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 287 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
| 277 std::unique_ptr<Buffer> buffer, | 288 std::unique_ptr<Buffer> buffer, |
| 278 const VideoCaptureFormat& frame_format, | 289 const VideoCaptureFormat& frame_format, |
| 279 base::TimeTicks reference_time, | 290 base::TimeTicks reference_time, |
| 280 base::TimeDelta timestamp) { | 291 base::TimeDelta timestamp) { |
| 281 // Currently, only I420 pixel format is supported. | 292 DCHECK(IsFormatSupported(frame_format.pixel_format)); |
| 282 DCHECK_EQ(media::PIXEL_FORMAT_I420, frame_format.pixel_format); | |
| 283 DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage); | 293 DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage); |
| 284 | 294 |
| 285 scoped_refptr<VideoFrame> frame; | 295 scoped_refptr<VideoFrame> frame; |
| 286 if (buffer->IsBackedByVideoFrame()) { | 296 if (buffer->IsBackedByVideoFrame()) { |
| 287 frame = buffer->GetVideoFrame(); | 297 frame = buffer->GetVideoFrame(); |
| 288 frame->set_timestamp(timestamp); | 298 frame->set_timestamp(timestamp); |
| 289 } else { | 299 } else { |
| 290 frame = VideoFrame::WrapExternalSharedMemory( | 300 frame = VideoFrame::WrapExternalSharedMemory( |
| 291 media::PIXEL_FORMAT_I420, frame_format.frame_size, | 301 frame_format.pixel_format, frame_format.frame_size, |
| 292 gfx::Rect(frame_format.frame_size), frame_format.frame_size, | 302 gfx::Rect(frame_format.frame_size), frame_format.frame_size, |
| 293 reinterpret_cast<uint8_t*>(buffer->data()), | 303 reinterpret_cast<uint8_t*>(buffer->data()), |
| 294 VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, | 304 VideoFrame::AllocationSize(frame_format.pixel_format, |
| 295 frame_format.frame_size), | 305 frame_format.frame_size), |
| 296 base::SharedMemory::NULLHandle(), 0u, timestamp); | 306 base::SharedMemory::NULLHandle(), 0u, timestamp); |
| 297 } | 307 } |
| 298 if (!frame) | 308 if (!frame) |
| 299 return; | 309 return; |
| 300 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, | 310 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
| 301 frame_format.frame_rate); | 311 frame_format.frame_rate); |
| 302 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, | 312 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, |
| 303 reference_time); | 313 reference_time); |
| 304 OnIncomingCapturedVideoFrame(std::move(buffer), frame); | 314 OnIncomingCapturedVideoFrame(std::move(buffer), frame); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 365 *y_plane_data = reinterpret_cast<uint8_t*>(buffer->data()); | 375 *y_plane_data = reinterpret_cast<uint8_t*>(buffer->data()); |
| 366 *u_plane_data = | 376 *u_plane_data = |
| 367 *y_plane_data + | 377 *y_plane_data + |
| 368 VideoFrame::PlaneSize(format, VideoFrame::kYPlane, dimensions).GetArea(); | 378 VideoFrame::PlaneSize(format, VideoFrame::kYPlane, dimensions).GetArea(); |
| 369 *v_plane_data = | 379 *v_plane_data = |
| 370 *u_plane_data + | 380 *u_plane_data + |
| 371 VideoFrame::PlaneSize(format, VideoFrame::kUPlane, dimensions).GetArea(); | 381 VideoFrame::PlaneSize(format, VideoFrame::kUPlane, dimensions).GetArea(); |
| 372 return buffer; | 382 return buffer; |
| 373 } | 383 } |
| 374 | 384 |
| 385 void VideoCaptureDeviceClient::OnIncomingCapturedY16Data( | |
| 386 const uint8_t* data, | |
| 387 int length, | |
| 388 const VideoCaptureFormat& frame_format, | |
| 389 base::TimeTicks reference_time, | |
| 390 base::TimeDelta timestamp) { | |
| 391 std::unique_ptr<Buffer> buffer(ReserveOutputBuffer(frame_format.frame_size, | |
| 392 media::PIXEL_FORMAT_Y16, | |
| 393 media::PIXEL_STORAGE_CPU)); | |
| 394 // The input |length| can be greater than the required buffer size because of | |
| 395 // paddings and/or alignments, but it cannot be smaller. | |
| 396 DCHECK_GE(static_cast<size_t>(length), frame_format.ImageAllocationSize()); | |
| 397 #if DCHECK_IS_ON() | |
| 398 dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; | |
| 399 if (dropped_frame_counter_ >= kMaxDroppedFrames) | |
| 400 OnError(FROM_HERE, "Too many frames dropped"); | |
| 401 #endif | |
| 402 // Failed to reserve output buffer, so drop the frame. | |
| 403 if (!buffer.get()) | |
| 404 return; | |
| 405 memcpy(buffer->data(), data, length); | |
| 406 const VideoCaptureFormat output_format = | |
| 407 VideoCaptureFormat(frame_format.frame_size, frame_format.frame_rate, | |
| 408 media::PIXEL_FORMAT_Y16, media::PIXEL_STORAGE_CPU); | |
| 409 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, | |
| 410 timestamp); | |
| 411 } | |
| 412 | |
| 375 } // namespace media | 413 } // namespace media |
| OLD | NEW |