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 "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 #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 "content/browser/renderer_host/media/video_capture_buffer_pool.h" | 17 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" |
| 18 #include "content/browser/renderer_host/media/video_capture_controller.h" | 18 #include "content/browser/renderer_host/media/video_capture_controller.h" |
| 19 #include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h" | 19 #include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h" |
| 20 #include "content/public/browser/browser_thread.h" | |
| 21 #include "media/base/bind_to_current_loop.h" | 20 #include "media/base/bind_to_current_loop.h" |
| 22 #include "media/base/media_switches.h" | 21 #include "media/base/media_switches.h" |
| 23 #include "media/base/video_capture_types.h" | 22 #include "media/base/video_capture_types.h" |
| 24 #include "media/base/video_frame.h" | 23 #include "media/base/video_frame.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; |
| 29 using media::VideoFrameMetadata; | 28 using media::VideoFrameMetadata; |
| 30 | 29 |
| 31 namespace content { | 30 namespace content { |
| 32 | 31 |
| 33 // Class combining a Client::Buffer interface implementation and a pool buffer | 32 // Class combining a Client::Buffer interface implementation and a pool buffer |
| 34 // implementation to guarantee proper cleanup on destruction on our side. | 33 // implementation to guarantee proper cleanup on destruction on our side. |
| 35 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { | 34 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { |
| 36 public: | 35 public: |
| 37 AutoReleaseBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, | 36 AutoReleaseBuffer(const scoped_refptr<ProducerVideoCaptureBufferPool>& pool, |
| 38 int buffer_id) | 37 int buffer_id) |
| 39 : id_(buffer_id), | 38 : id_(buffer_id), |
| 40 pool_(pool), | 39 pool_(pool), |
|
miu
2016/09/12 20:16:46
For example, when passing scoped_refptr by value,
chfremer
2016/09/12 22:23:33
Acknowledged.
| |
| 41 buffer_handle_(pool_->GetBufferHandle(buffer_id)) { | 40 buffer_handle_(pool_->GetBufferHandle(buffer_id)) { |
| 42 DCHECK(pool_.get()); | 41 DCHECK(pool_.get()); |
| 43 } | 42 } |
| 44 int id() const override { return id_; } | 43 int id() const override { return id_; } |
| 45 gfx::Size dimensions() const override { return buffer_handle_->dimensions(); } | 44 gfx::Size dimensions() const override { return buffer_handle_->dimensions(); } |
| 46 size_t mapped_size() const override { return buffer_handle_->mapped_size(); } | 45 size_t mapped_size() const override { return buffer_handle_->mapped_size(); } |
| 47 void* data(int plane) override { return buffer_handle_->data(plane); } | 46 void* data(int plane) override { return buffer_handle_->data(plane); } |
| 48 ClientBuffer AsClientBuffer(int plane) override { | 47 ClientBuffer AsClientBuffer(int plane) override { |
| 49 return buffer_handle_->AsClientBuffer(plane); | 48 return buffer_handle_->AsClientBuffer(plane); |
| 50 } | 49 } |
| 51 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 50 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
| 52 base::FileDescriptor AsPlatformFile() override { | 51 base::FileDescriptor AsPlatformFile() override { |
| 53 return buffer_handle_->AsPlatformFile(); | 52 return buffer_handle_->AsPlatformFile(); |
| 54 } | 53 } |
| 55 #endif | 54 #endif |
| 56 | 55 |
| 57 private: | 56 private: |
| 58 ~AutoReleaseBuffer() override { pool_->RelinquishProducerReservation(id_); } | 57 ~AutoReleaseBuffer() override { pool_->RelinquishProducerReservation(id_); } |
| 59 | 58 |
| 60 const int id_; | 59 const int id_; |
| 61 const scoped_refptr<VideoCaptureBufferPool> pool_; | 60 const scoped_refptr<ProducerVideoCaptureBufferPool> pool_; |
| 62 const std::unique_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle_; | 61 const std::unique_ptr<VideoCaptureBufferPoolBufferHandle> buffer_handle_; |
| 63 }; | 62 }; |
| 64 | 63 |
| 65 VideoCaptureDeviceClient::VideoCaptureDeviceClient( | 64 VideoCaptureDeviceClient::VideoCaptureDeviceClient( |
| 66 const base::WeakPtr<VideoCaptureController>& controller, | 65 std::unique_ptr<VideoFrameReceiver> receiver, |
| 67 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool) | 66 const scoped_refptr<ProducerVideoCaptureBufferPool>& buffer_pool, |
| 68 : controller_(controller), | 67 const VideoCaptureJpegDecoderFactoryCB& jpeg_decoder_factory) |
| 68 : receiver_(std::move(receiver)), | |
| 69 jpeg_decoder_factory_callback_(jpeg_decoder_factory), | |
| 69 external_jpeg_decoder_initialized_(false), | 70 external_jpeg_decoder_initialized_(false), |
| 70 buffer_pool_(buffer_pool), | 71 buffer_pool_(buffer_pool), |
| 71 use_gpu_memory_buffers_(base::CommandLine::ForCurrentProcess()->HasSwitch( | 72 use_gpu_memory_buffers_(base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 72 switches::kUseGpuMemoryBuffersForCapture)), | 73 switches::kUseGpuMemoryBuffersForCapture)), |
| 73 last_captured_pixel_format_(media::PIXEL_FORMAT_UNKNOWN) { | 74 last_captured_pixel_format_(media::PIXEL_FORMAT_UNKNOWN) {} |
| 74 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 75 } | |
| 76 | 75 |
| 77 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() { | 76 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() { |
| 78 // This should be on the platform auxiliary thread since | 77 // This should be on the platform auxiliary thread since |
| 79 // |external_jpeg_decoder_| need to be destructed on the same thread as | 78 // |external_jpeg_decoder_| need to be destructed on the same thread as |
| 80 // OnIncomingCapturedData. | 79 // OnIncomingCapturedData. |
| 81 } | 80 } |
| 82 | 81 |
| 83 void VideoCaptureDeviceClient::OnIncomingCapturedData( | 82 void VideoCaptureDeviceClient::OnIncomingCapturedData( |
| 84 const uint8_t* data, | 83 const uint8_t* data, |
| 85 int length, | 84 int length, |
| 86 const VideoCaptureFormat& frame_format, | 85 const VideoCaptureFormat& frame_format, |
| 87 int rotation, | 86 int rotation, |
| 88 base::TimeTicks reference_time, | 87 base::TimeTicks reference_time, |
| 89 base::TimeDelta timestamp) { | 88 base::TimeDelta timestamp) { |
| 90 TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedData"); | 89 TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedData"); |
| 91 DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage); | 90 DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage); |
| 92 | 91 |
| 93 if (last_captured_pixel_format_ != frame_format.pixel_format) { | 92 if (last_captured_pixel_format_ != frame_format.pixel_format) { |
| 94 OnLog("Pixel format: " + | 93 OnLog("Pixel format: " + |
| 95 media::VideoPixelFormatToString(frame_format.pixel_format)); | 94 media::VideoPixelFormatToString(frame_format.pixel_format)); |
| 96 last_captured_pixel_format_ = frame_format.pixel_format; | 95 last_captured_pixel_format_ = frame_format.pixel_format; |
| 97 | 96 |
| 98 if (frame_format.pixel_format == media::PIXEL_FORMAT_MJPEG && | 97 if (frame_format.pixel_format == media::PIXEL_FORMAT_MJPEG && |
| 99 !external_jpeg_decoder_initialized_) { | 98 !external_jpeg_decoder_initialized_) { |
| 100 external_jpeg_decoder_initialized_ = true; | 99 external_jpeg_decoder_initialized_ = true; |
| 101 external_jpeg_decoder_.reset(new VideoCaptureGpuJpegDecoder(base::Bind( | 100 external_jpeg_decoder_ = jpeg_decoder_factory_callback_.Run(); |
| 102 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, | |
| 103 controller_))); | |
| 104 external_jpeg_decoder_->Initialize(); | 101 external_jpeg_decoder_->Initialize(); |
| 105 } | 102 } |
| 106 } | 103 } |
| 107 | 104 |
| 108 if (!frame_format.IsValid()) | 105 if (!frame_format.IsValid()) |
| 109 return; | 106 return; |
| 110 | 107 |
| 111 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest | 108 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest |
| 112 // bit decomposition of {width, height}, grabbing the odd and even parts. | 109 // bit decomposition of {width, height}, grabbing the odd and even parts. |
| 113 const int chopped_width = frame_format.frame_size.width() & 1; | 110 const int chopped_width = frame_format.frame_size.width() & 1; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 const gfx::Size& frame_size, | 266 const gfx::Size& frame_size, |
| 270 media::VideoPixelFormat pixel_format, | 267 media::VideoPixelFormat pixel_format, |
| 271 media::VideoPixelStorage pixel_storage) { | 268 media::VideoPixelStorage pixel_storage) { |
| 272 DCHECK_GT(frame_size.width(), 0); | 269 DCHECK_GT(frame_size.width(), 0); |
| 273 DCHECK_GT(frame_size.height(), 0); | 270 DCHECK_GT(frame_size.height(), 0); |
| 274 // Currently, only I420 pixel format is supported. | 271 // Currently, only I420 pixel format is supported. |
| 275 DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format); | 272 DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format); |
| 276 | 273 |
| 277 // 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 |
| 278 // it's a ShMem GMB or a DmaBuf GMB. | 275 // it's a ShMem GMB or a DmaBuf GMB. |
| 279 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; | 276 int buffer_id_to_drop = ProducerVideoCaptureBufferPool::kInvalidId; |
| 280 const int buffer_id = buffer_pool_->ReserveForProducer( | 277 const int buffer_id = buffer_pool_->ReserveForProducer( |
| 281 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop); | 278 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop); |
| 282 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { | 279 if (buffer_id_to_drop != ProducerVideoCaptureBufferPool::kInvalidId) |
| 283 BrowserThread::PostTask(BrowserThread::IO, | 280 receiver_->OnBufferDestroyed(buffer_id_to_drop); |
| 284 FROM_HERE, | 281 if (buffer_id == ProducerVideoCaptureBufferPool::kInvalidId) |
| 285 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, | |
| 286 controller_, buffer_id_to_drop)); | |
| 287 } | |
| 288 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | |
| 289 return nullptr; | 282 return nullptr; |
| 290 return base::WrapUnique<Buffer>( | 283 return base::WrapUnique<Buffer>( |
| 291 new AutoReleaseBuffer(buffer_pool_, buffer_id)); | 284 new AutoReleaseBuffer(buffer_pool_, buffer_id)); |
| 292 } | 285 } |
| 293 | 286 |
| 294 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 287 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
| 295 std::unique_ptr<Buffer> buffer, | 288 std::unique_ptr<Buffer> buffer, |
| 296 const VideoCaptureFormat& frame_format, | 289 const VideoCaptureFormat& frame_format, |
| 297 base::TimeTicks reference_time, | 290 base::TimeTicks reference_time, |
| 298 base::TimeDelta timestamp) { | 291 base::TimeDelta timestamp) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 328 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, | 321 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
| 329 frame_format.frame_rate); | 322 frame_format.frame_rate); |
| 330 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, | 323 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, |
| 331 reference_time); | 324 reference_time); |
| 332 OnIncomingCapturedVideoFrame(std::move(buffer), frame); | 325 OnIncomingCapturedVideoFrame(std::move(buffer), frame); |
| 333 } | 326 } |
| 334 | 327 |
| 335 void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( | 328 void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( |
| 336 std::unique_ptr<Buffer> buffer, | 329 std::unique_ptr<Buffer> buffer, |
| 337 const scoped_refptr<VideoFrame>& frame) { | 330 const scoped_refptr<VideoFrame>& frame) { |
| 338 BrowserThread::PostTask( | 331 receiver_->OnIncomingCapturedVideoFrame(std::move(buffer), frame); |
| 339 BrowserThread::IO, FROM_HERE, | |
| 340 base::Bind( | |
| 341 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, | |
| 342 controller_, base::Passed(&buffer), frame)); | |
| 343 } | 332 } |
| 344 | 333 |
| 345 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 334 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
| 346 VideoCaptureDeviceClient::ResurrectLastOutputBuffer( | 335 VideoCaptureDeviceClient::ResurrectLastOutputBuffer( |
| 347 const gfx::Size& dimensions, | 336 const gfx::Size& dimensions, |
| 348 media::VideoPixelFormat format, | 337 media::VideoPixelFormat format, |
| 349 media::VideoPixelStorage storage) { | 338 media::VideoPixelStorage storage) { |
| 350 const int buffer_id = | 339 const int buffer_id = |
| 351 buffer_pool_->ResurrectLastForProducer(dimensions, format, storage); | 340 buffer_pool_->ResurrectLastForProducer(dimensions, format, storage); |
| 352 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 341 if (buffer_id == ProducerVideoCaptureBufferPool::kInvalidId) |
| 353 return nullptr; | 342 return nullptr; |
| 354 return base::WrapUnique<Buffer>( | 343 return base::WrapUnique<Buffer>( |
| 355 new AutoReleaseBuffer(buffer_pool_, buffer_id)); | 344 new AutoReleaseBuffer(buffer_pool_, buffer_id)); |
| 356 } | 345 } |
| 357 | 346 |
| 358 void VideoCaptureDeviceClient::OnError( | 347 void VideoCaptureDeviceClient::OnError( |
| 359 const tracked_objects::Location& from_here, | 348 const tracked_objects::Location& from_here, |
| 360 const std::string& reason) { | 349 const std::string& reason) { |
| 361 const std::string log_message = base::StringPrintf( | 350 const std::string log_message = base::StringPrintf( |
| 362 "error@ %s, %s, OS message: %s", from_here.ToString().c_str(), | 351 "error@ %s, %s, OS message: %s", from_here.ToString().c_str(), |
| 363 reason.c_str(), | 352 reason.c_str(), |
| 364 logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode()) | 353 logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode()) |
| 365 .c_str()); | 354 .c_str()); |
| 366 DLOG(ERROR) << log_message; | 355 DLOG(ERROR) << log_message; |
| 367 OnLog(log_message); | 356 OnLog(log_message); |
| 368 BrowserThread::PostTask(BrowserThread::IO, | 357 receiver_->OnError(); |
| 369 FROM_HERE, | |
| 370 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); | |
| 371 } | 358 } |
| 372 | 359 |
| 373 void VideoCaptureDeviceClient::OnLog( | 360 void VideoCaptureDeviceClient::OnLog( |
| 374 const std::string& message) { | 361 const std::string& message) { |
| 375 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 362 receiver_->OnLog(message); |
| 376 base::Bind(&VideoCaptureController::DoLogOnIOThread, | |
| 377 controller_, message)); | |
| 378 } | 363 } |
| 379 | 364 |
| 380 double VideoCaptureDeviceClient::GetBufferPoolUtilization() const { | 365 double VideoCaptureDeviceClient::GetBufferPoolUtilization() const { |
| 381 // VideoCaptureBufferPool::GetBufferPoolUtilization() is thread-safe. | |
| 382 return buffer_pool_->GetBufferPoolUtilization(); | 366 return buffer_pool_->GetBufferPoolUtilization(); |
| 383 } | 367 } |
| 384 | 368 |
| 385 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 369 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
| 386 VideoCaptureDeviceClient::ReserveI420OutputBuffer( | 370 VideoCaptureDeviceClient::ReserveI420OutputBuffer( |
| 387 const gfx::Size& dimensions, | 371 const gfx::Size& dimensions, |
| 388 media::VideoPixelStorage storage, | 372 media::VideoPixelStorage storage, |
| 389 uint8_t** y_plane_data, | 373 uint8_t** y_plane_data, |
| 390 uint8_t** u_plane_data, | 374 uint8_t** u_plane_data, |
| 391 uint8_t** v_plane_data) { | 375 uint8_t** v_plane_data) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 421 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kUPlane)); | 405 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kUPlane)); |
| 422 *v_plane_data = | 406 *v_plane_data = |
| 423 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kVPlane)); | 407 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kVPlane)); |
| 424 return buffer; | 408 return buffer; |
| 425 } | 409 } |
| 426 NOTREACHED(); | 410 NOTREACHED(); |
| 427 return std::unique_ptr<Buffer>(); | 411 return std::unique_ptr<Buffer>(); |
| 428 } | 412 } |
| 429 | 413 |
| 430 } // namespace content | 414 } // namespace content |
| OLD | NEW |